Esempio n. 1
0
        /// <summary>
        /// Take first 7 full node key pairs to announce election.
        /// </summary>
        /// <returns>Return 7 candidates key pairs.</returns>
        public async Task <List <ECKeyPair> > ElectionContract_AnnounceElection_Test()
        {
            var candidatesKeyPairs = ValidationDataCenterKeyPairs.Take(CandidatesCount).ToList();

            var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey);

            balanceBeforeAnnouncing.ShouldBe(ElectionContractConstants.UserInitializeTokenAmount);

            candidatesKeyPairs.ForEach(async kp => await AnnounceElectionAsync(kp));

            var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey);

            // 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);
        }
Esempio n. 2
0
        public async Task <List <string> > ElectionContract_GetVictories_ValidCandidatesEnough_Test()
        {
            await NextRound(BootMinerKeyPair);

            ValidationDataCenterKeyPairs.ForEach(async kp => await AnnounceElectionAsync(kp));

            var moreVotesCandidates = ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList();

            moreVotesCandidates.ForEach(async kp =>
                                        await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 2));

            var lessVotesCandidates = ValidationDataCenterKeyPairs.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount).Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList();

            lessVotesCandidates.ForEach(async kp =>
                                        await VoteToCandidate(VoterKeyPairs[0], kp.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);
        }
Esempio n. 3
0
        public async Task <List <ECKeyPair> > ElectionContract_GetVictories_NotAllCandidatesGetVotes_Test()
        {
            await NextRound(BootMinerKeyPair);

            foreach (var keyPair in ValidationDataCenterKeyPairs)
            {
                await AnnounceElectionAsync(keyPair);
            }

            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())).Value
                            .Select(p => p.ToHex()).ToList();

            foreach (var validCandidate in validCandidates)
            {
                victories.ShouldContain(validCandidate.PublicKey.ToHex());
            }

            return(validCandidates);
        }
Esempio n. 4
0
        public async Task GetPageableCandidateInformation_Test()
        {
            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);

            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);
        }
Esempio n. 5
0
        public async Task GetTermSnapshot_Test()
        {
            //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
            {
                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);
            }
        }
Esempio n. 6
0
        public async Task <List <string> > ElectionContract_GetVictories_ValidCandidatesNotEnough_Test()
        {
            const int amount = 100;

            await NextRound(BootMinerKeyPair);

            foreach (var keyPair in ValidationDataCenterKeyPairs)
            {
                await AnnounceElectionAsync(keyPair);
            }

            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);
            }

            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);
            }

            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());
            }

            return(victories);
        }
Esempio n. 7
0
        #pragma warning disable xUnit1013
        public async Task ElectionContract_QuiteElection_Test()
        {
            const int quitCount = 2;

            var candidates = await ElectionContract_AnnounceElection_Test();

            // Check VotingEvent before quiting election.
            {
                var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput
                {
                    VotingItemId = MinerElectionVotingItemId
                });

                votingItem.Options.Count.ShouldBe(candidates.Count);
            }

            var quitCandidates = ValidationDataCenterKeyPairs.Take(quitCount).ToList();

            var balancesBeforeQuiting = new Dictionary <ECKeyPair, long>();

            // Record balances before quiting election.
            foreach (var quitCandidate in quitCandidates)
            {
                balancesBeforeQuiting.Add(quitCandidate, await GetNativeTokenBalance(quitCandidate.PublicKey));
            }

            foreach (var keyPair in quitCandidates)
            {
                await QuitElectionAsync(keyPair);
            }

            // Check balances after quiting election.
            foreach (var quitCandidate in quitCandidates)
            {
                var balance = await GetNativeTokenBalance(quitCandidate.PublicKey);

                balance.ShouldBe(balancesBeforeQuiting[quitCandidate] + ElectionContractConstants.LockTokenForElection);
            }

            // Check VotingEvent after quiting election.
            {
                var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput
                {
                    VotingItemId = MinerElectionVotingItemId
                });

                votingItem.Options.Count.ShouldBe(candidates.Count - quitCount);
            }
        }
        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(new Empty());

                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();
            }
        }
Esempio n. 9
0
        public async Task ElectionContract_GetVictories_CandidatesNotEnough_Test()
        {
            // To get previous round information.
            await NextRound(BootMinerKeyPair);

            ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1).ToList()
            .ForEach(async kp => await AnnounceElectionAsync(kp));

            var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value
                            .Select(p => p.ToHex()).ToList();

            // Same as initial miners.
            victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount);
            foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex()))
            {
                victories.ShouldContain(initialMiner);
            }
        }
Esempio n. 10
0
        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);

            var voter = VoterKeyPairs.First();

            await
            VoteToCandidate(voter, newCandidate.PublicKey.ToHex(), 100 * 86400, 200);

            var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty());

            victories.Value.Select(o => o.ToHex()).ShouldContain(newCandidate.PublicKey.ToHex());
        }
Esempio n. 11
0
        public async Task UserVote_And_GetProfitAmount_Test()
        {
            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 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 round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty());

                round.TermNumber.ShouldBe(1);
            }

            await ProduceBlocks(BootMinerKeyPair, 10);
            await NextTerm(BootMinerKeyPair);

            {
                var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty());

                round.TermNumber.ShouldBe(2);
            }

            await ProduceBlocks(ValidationDataCenterKeyPairs[0], 10);
            await NextTerm(ValidationDataCenterKeyPairs[0]);

            {
                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);
        }
Esempio n. 12
0
        public async Task Candidates_NotEnough_Test()
        {
            //await ElectionContractStub.RegisterElectionVotingEvent.SendAsync(new Empty());

            //await InitializeVoters();
            await InitializeCandidates(EconomicContractsTestConstants.InitialCoreDataCenterCount);

            var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty());

            var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount)
                               .Select(_ => Hash.FromString("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]);

            foreach (var candidateKeyPair in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants
                                                                               .InitialCoreDataCenterCount))
            {
                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.TimeEachTerm + 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               = Hash.FromString("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.TimeEachTerm + 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 = Hash.FromMessage(randomHash), // Not same as before.
                InValue = Hash.FromString("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()));
        }
Esempio n. 13
0
        public async Task CheckTreasuryProfitsDistribution_Test()
        {
            const long txFee = 1_00000000L;
            long rewardAmount;
            var updatedBackupSubsidy = 0L;
            var updatedBasicReward = 0L;
            var updatedVotesWeightReward = 0L;
            var updatedReElectionReward = 0L;
            var updatedCitizenWelfare = 0L;

            var treasuryScheme =
                await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]);

            // Prepare candidates and votes.
            {
                // SampleKeyPairs[13...47] announce election.
                ValidationDataCenterKeyPairs.ForEach(async kp => await AnnounceElectionAsync(kp));

                // 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();
                moreVotesCandidates.ForEach(async kp =>
                    await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 2));

                // SampleKeyPairs[18...22] get 1 votes.
                var lessVotesCandidates = ValidationDataCenterKeyPairs
                    .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount)
                    .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList();
                lessVotesCandidates.ForEach(async kp =>
                    await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 1));

                // Check the count of voted candidates, should be 10.
                var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty());
                votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount * 2);
            }

            // 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);
            }

            // 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.
                {
                    var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = treasuryScheme.VirtualAddress,
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    balance.Balance.ShouldBe(0);
                }

                // Backup subsidy.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod);
                    releasedInformation.TotalShares.ShouldBe(
                        EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 5);
                }

                // Amount of backup subsidy.
                {
                    var amount = await GetProfitAmount(ProfitType.BackupSubsidy);
                    updatedBackupSubsidy +=
                        rewardAmount / 5 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    amount.ShouldBe(updatedBackupSubsidy);
                }

                // Basic reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(0);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(-rewardAmount * 2 / 5);
                }

                // Amount of basic reward.
                {
                    var amount = await GetProfitAmount(ProfitType.BasicMinerReward);
                    amount.ShouldBe(0);
                }

                // Votes weights reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.VotesWeightReward, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(0);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(-rewardAmount / 10);
                }

                // Amount of votes weights reward.
                {
                    var amount = await GetProfitAmount(ProfitType.VotesWeightReward);
                    amount.ShouldBe(0);
                }

                // Re-election reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.ReElectionReward, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(0);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(-rewardAmount / 10);
                }

                // Amount of re-election reward.
                {
                    var amount = await GetProfitAmount(ProfitType.ReElectionReward);
                    amount.ShouldBe(0);
                }

                // Citizen welfare.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(0);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(-rewardAmount / 5);
                }

                // Amount of citizen welfare.
                {
                    var amount = await GetProfitAmount(ProfitType.CitizenWelfare);
                    amount.ShouldBe(0);
                }
            }

            await GenerateMiningReward(3);

            // Check released profits of second term.
            {
                rewardAmount = await GetReleasedAmount();
                const long currentPeriod = 2L;

                // Check balance of Treasury general ledger.
                {
                    var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = treasuryScheme.VirtualAddress,
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    balance.Balance.ShouldBe(0);
                }

                // Backup subsidy.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod);
                    releasedInformation.TotalShares.ShouldBe(
                        EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 5);
                }

                // Amount of backup subsidy.
                {
                    var amount = await GetProfitAmount(ProfitType.BackupSubsidy);
                    updatedBackupSubsidy +=
                        rewardAmount / 5 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    amount.ShouldBe(updatedBackupSubsidy);
                }

                // Basic reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod);
                    releasedInformation.TotalShares.ShouldBe(9);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount * 2 / 5);
                }

                // Amount of basic reward.
                {
                    var amount = await GetProfitAmount(ProfitType.BasicMinerReward);
                    updatedBasicReward += rewardAmount * 2 / 5 / 9;
                    amount.ShouldBe(updatedBasicReward);
                }

                // Votes weights reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.VotesWeightReward, currentPeriod);
                    // First 5 victories each obtained 2 votes, last 4 victories each obtained 1 vote.
                    releasedInformation.TotalShares.ShouldBe(2 * 5 + 4);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 10);
                }

                // Amount of votes weights reward.
                {
                    var amount = await GetProfitAmount(ProfitType.VotesWeightReward);
                    updatedVotesWeightReward += rewardAmount / 10 * 2 / 14;
                    amount.ShouldBe(updatedVotesWeightReward);
                }

                // Re-election reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.ReElectionReward, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(0);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(-rewardAmount / 10);
                }

                // Amount of re-election reward.
                {
                    var amount = await GetProfitAmount(ProfitType.ReElectionReward);
                    amount.ShouldBe(0);
                }

                // Citizen welfare.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 5);

                    // Amount of citizen welfare.
                    var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringInput
                        {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 / 5 / releasedInformation.TotalShares;
                    amount.ShouldBeLessThan(updatedCitizenWelfare);
                }
            }

            await GenerateMiningReward(4);

            // Check released profits of third term.
            {
                rewardAmount = await GetReleasedAmount();
                const long currentPeriod = 3L;

                // Check balance of Treasury general ledger.
                {
                    var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = treasuryScheme.VirtualAddress,
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    balance.Balance.ShouldBe(0);
                }

                // Backup subsidy.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod);
                    releasedInformation.TotalShares.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 5);
                }

                // Amount of backup subsidy.
                {
                    var amount = await GetProfitAmount(ProfitType.BackupSubsidy);
                    updatedBackupSubsidy +=
                        rewardAmount / 5 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5);
                    amount.ShouldBe(updatedBackupSubsidy);
                }

                // Basic reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod);
                    releasedInformation.TotalShares.ShouldBe(9);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount * 2 / 5);
                }

                // Amount of basic reward.
                {
                    var amount = await GetProfitAmount(ProfitType.BasicMinerReward);
                    updatedBasicReward += rewardAmount * 2 / 5 / 9;
                    amount.ShouldBe(updatedBasicReward);
                }

                // Votes weights reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.VotesWeightReward, currentPeriod);
                    // First 5 victories each obtained 2 votes, last 4 victories each obtained 1 vote.
                    releasedInformation.TotalShares.ShouldBe(2 * 5 + 4);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 10);
                }

                // Amount of votes weights reward.
                {
                    var amount = await GetProfitAmount(ProfitType.VotesWeightReward);
                    updatedVotesWeightReward += rewardAmount / 10 * 2 / 14;
                    amount.ShouldBe(updatedVotesWeightReward);
                }

                // Re-election reward.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.ReElectionReward, currentPeriod);
                    releasedInformation.IsReleased.ShouldBeTrue();
                    releasedInformation.TotalShares.ShouldBe(9);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 10);
                }

                // Amount of re-election reward.
                {
                    var amount = await GetProfitAmount(ProfitType.ReElectionReward);
                    amount.ShouldBe(rewardAmount / 10 / 9);
                }

                // Citizen welfare.
                {
                    var releasedInformation =
                        await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod);
                    releasedInformation.ProfitsAmount[EconomicContractsTestConstants.NativeTokenSymbol]
                        .ShouldBe(rewardAmount / 5);

                    // Amount of citizen welfare.
                    var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringInput
                        {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 / 5 / 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;

                var profitTester = GetProfitContractTester(VoterKeyPairs[0]);
                var profitAmount = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                {
                    SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare],
                    Symbol = "ELF"
                })).Value;
                profitAmount.ShouldBeGreaterThan(0);

                var profitResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                {
                    SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare],
                    Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                });
                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);
            }

            await GenerateMiningReward(5);

            //query and profit miner profit
            {
                foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants
                    .InitialCoreDataCenterCount))
                {
                    var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = Address.FromPublicKey(miner.PublicKey),
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    })).Balance;

                    var profitTester = GetProfitContractTester(miner);

                    //basic Shares - 40%
                    var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward],
                        Symbol = "ELF"
                    })).Value;
                    basicMinerRewardAmount.ShouldBeGreaterThan(0);

                    //vote Shares - 10%
                    var votesWeightRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.VotesWeightReward],
                        Symbol = "ELF"
                    })).Value;
                    votesWeightRewardAmount.ShouldBeGreaterThan(0);

                    //re-election Shares - 10%
                    var reElectionBalance = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.ReElectionReward],
                        Symbol = "ELF"
                    })).Value;
                    reElectionBalance.ShouldBeGreaterThan(0);

                    //backup Shares - 20%
                    var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy],
                        Symbol = "ELF"
                    })).Value;
                    backupBalance.ShouldBeGreaterThan(0);

                    //Profit all
                    var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);

                    var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.VotesWeightReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);

                    var reElectionResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.ReElectionReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    reElectionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);

                    var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);

                    var afterToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = Address.FromPublicKey(miner.PublicKey),
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    })).Balance;

                    afterToken.ShouldBe(beforeToken + basicMinerRewardAmount + votesWeightRewardAmount +
                                        reElectionBalance + backupBalance - txFee * 4);
                }
            }

            await GenerateMiningReward(6);

            //query and profit miner profit
            {
                foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants
                    .InitialCoreDataCenterCount))
                {
                    var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                    {
                        Owner = Address.FromPublicKey(miner.PublicKey),
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    })).Balance;

                    var profitTester = GetProfitContractTester(miner);

                    //basic Shares - 40%
                    var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward],
                        Symbol = "ELF"
                    })).Value;
                    basicMinerRewardAmount.ShouldBeGreaterThan(0);

                    //vote Shares - 10%
                    var votesWeightRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.VotesWeightReward],
                        Symbol = "ELF"
                    })).Value;
                    votesWeightRewardAmount.ShouldBeGreaterThan(0);

                    //re-election Shares - 10%
                    var reElectionBalance = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.ReElectionReward],
                        Symbol = "ELF"
                    })).Value;
                    reElectionBalance.ShouldBeGreaterThan(0);

                    //backup Shares - 20%
                    var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy],
                        Symbol = "ELF"
                    })).Value;
                    backupBalance.ShouldBeGreaterThan(0);

                    //Profit all
                    var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);
                    
                    {
                        var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                        {
                            Owner = Address.FromPublicKey(miner.PublicKey),
                            Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                        })).Balance;
                        balance.ShouldBe(beforeToken + basicMinerRewardAmount - txFee);
                    }

                    var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.VotesWeightReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);
                    
                    {
                        var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                        {
                            Owner = Address.FromPublicKey(miner.PublicKey),
                            Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                        })).Balance;
                        balance.ShouldBe(beforeToken + basicMinerRewardAmount + votesWeightRewardAmount - txFee * 2);
                    }

                    var reElectionResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.ReElectionReward],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    reElectionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);
                    
                    {
                        var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                        {
                            Owner = Address.FromPublicKey(miner.PublicKey),
                            Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                        })).Balance;
                        balance.ShouldBe(beforeToken + basicMinerRewardAmount + votesWeightRewardAmount +
                                         reElectionBalance - txFee * 3);
                    }

                    var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput
                    {
                        SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy],
                        Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                    });
                    backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);
                    
                    {
                        var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput
                        {
                            Owner = Address.FromPublicKey(miner.PublicKey),
                            Symbol = EconomicContractsTestConstants.NativeTokenSymbol
                        })).Balance;
                        balance.ShouldBe(beforeToken + basicMinerRewardAmount + votesWeightRewardAmount +
                                         reElectionBalance + backupBalance - txFee * 4);
                    }
                }
            }
        }