private void TryToBecomeAValidationDataCenter(VoteMinerInput input, long candidateVotesAmount,
                                                      DataCenterRankingList rankingList)
        {
            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;
                }
            }

            if (replaceWillHappen)
            {
                State.DataCentersRankingList.Value.DataCenters.Remove(minimumVotesCandidate);
                State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey,
                                                                   candidateVotesAmount);
                NotifyProfitReplaceCandidateInDataCenter(minimumVotesCandidate, input.CandidatePubkey);
            }
        }
        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))));
        }
예제 #3
0
        /// <summary>
        /// Call the Vote function of VoteContract to do a voting.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Empty Vote(VoteMinerInput input)
        {
            // Check candidate information map instead of candidates.
            var targetInformation = State.CandidateInformationMap[input.CandidatePubkey];

            AssertValidCandidateInformation(targetInformation);

            var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds;

            AssertValidLockSeconds(lockSeconds);

            State.LockTimeMap[Context.TransactionId] = lockSeconds;

            var recoveredPublicKey = Context.RecoverPublicKey();

            UpdateElectorInformation(recoveredPublicKey, input.Amount);

            var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount);

            CallTokenContractLock(input.Amount);

            CallTokenContractIssue(input.Amount);

            CallVoteContractVote(input.Amount, input.CandidatePubkey);

            var votesWeight = GetVotesWeight(input.Amount, lockSeconds);

            CallProfitContractAddBeneficiary(votesWeight, lockSeconds);

            var rankingList = State.DataCentersRankingList.Value;

            if (State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                rankingList.DataCenters[input.CandidatePubkey] =
                    rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount);
                State.DataCentersRankingList.Value = rankingList;
            }

            if (State.Candidates.Value.Value.Count > GetValidationDataCenterCount() &&
                !State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList);
            }

            return(new Empty());
        }
        /// <summary>
        /// Call the Vote function of VoteContract to do a voting.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Hash Vote(VoteMinerInput input)
        {
            // Check candidate information map instead of candidates.
            var targetInformation = State.CandidateInformationMap[input.CandidatePubkey];

            AssertValidCandidateInformation(targetInformation);

            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;

            var recoveredPublicKey = Context.RecoverPublicKey();

            UpdateElectorInformation(recoveredPublicKey, input.Amount, voteId);

            var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount, voteId);

            LockTokensOfVoter(input.Amount, voteId);
            IssueOrTransferTokensToVoter(input.Amount);
            CallVoteContractVote(input.Amount, input.CandidatePubkey, voteId);
            AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds);

            var rankingList = State.DataCentersRankingList.Value;

            if (State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                rankingList.DataCenters[input.CandidatePubkey] =
                    rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount);
                State.DataCentersRankingList.Value = rankingList;
            }

            if (State.Candidates.Value.Value.Count > GetValidationDataCenterCount() &&
                !State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList);
            }

            return(voteId);
        }
예제 #5
0
        private void TryToBecomeAValidationDataCenter(VoteMinerInput input, long candidateVotesAmount,
                                                      DataCenterRankingList rankingList)
        {
            var  minimumVotes          = candidateVotesAmount;
            var  minimumVotesCandidate = input.CandidatePubkey;
            bool replaceWillHappen     = false;

            foreach (var pubkeyToVotesAmount in rankingList.DataCenters.Reverse())
            {
                if (pubkeyToVotesAmount.Value < minimumVotes)
                {
                    replaceWillHappen     = true;
                    minimumVotesCandidate = pubkeyToVotesAmount.Key;
                    break;
                }
            }

            if (replaceWillHappen)
            {
                State.DataCentersRankingList.Value.DataCenters.Remove(minimumVotesCandidate);
                State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey,
                                                                   candidateVotesAmount);
                State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
                {
                    SchemeId    = State.SubsidyHash.Value,
                    Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumVotesCandidate))
                });
                State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
                {
                    SchemeId         = State.SubsidyHash.Value,
                    BeneficiaryShare = new BeneficiaryShare
                    {
                        Beneficiary =
                            Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)),
                        Shares = 1
                    }
                });
            }
        }
예제 #6
0
        public override Empty Vote(VoteMinerInput input)
        {
            var lockTime = input.LockTimeUnit == LockTimeUnit.Days ? input.LockTime : input.LockTime * 30;

            Assert(lockTime >= 90, "Should lock token for at least 90 days.");
            State.LockTimeMap[Context.TransactionId] = lockTime;

            State.TokenContract.Transfer.Send(new TransferInput
            {
                Symbol = ElectionContractConsts.VoteSymbol,
                To     = Context.Sender,
                Amount = input.Amount,
                Memo   = "Get VOTEs."
            });

            State.TokenContract.Lock.Send(new LockInput
            {
                From   = Context.Sender,
                Symbol = Context.Variables.NativeSymbol,
                LockId = Context.TransactionId,
                Amount = input.Amount,
                To     = Context.Self,
                Usage  = $"Voting for {ElectionContractConsts.Topic}"
            });

            State.VoteContract.Vote.Send(new VoteInput
            {
                Topic   = ElectionContractConsts.Topic,
                Sponsor = Context.Self,
                Amount  = input.Amount,
                Option  = input.CandidatePublicKey,
                Voter   = Context.Sender,
                VoteId  = Context.TransactionId
            });

            return(new Empty());
        }
예제 #7
0
        /// <summary>
        /// Call the Vote function of VoteContract to do a voting.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Empty Vote(VoteMinerInput input)
        {
            // Check candidate information map instead of candidates.
            var targetInformation = State.CandidateInformationMap[input.CandidatePubkey];

            Assert(targetInformation != null, "Candidate not found.");
            if (targetInformation == null)
            {
                return(new Empty());                           // Just to avoid IDE warning.
            }
            Assert(targetInformation.IsCurrentCandidate, "Candidate quited election.");

            var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds;

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

            State.LockTimeMap[Context.TransactionId] = lockSeconds;

            var recoveredPublicKey = Context.RecoverPublicKey();

            UpdateElectorInformation(recoveredPublicKey, input.Amount);

            var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount);

            State.TokenContract.Lock.Send(new LockInput
            {
                Address = Context.Sender,
                Symbol  = Context.Variables.NativeSymbol,
                LockId  = Context.TransactionId,
                Amount  = GetElfAmount(input.Amount),
                Usage   = "Voting for Main Chain Miner Election."
            });

            State.TokenContract.Issue.Send(new IssueInput
            {
                Symbol = ElectionContractConstants.VoteSymbol,
                To     = Context.Sender,
                Amount = input.Amount,
                Memo   = "Issue VOTEs."
            });

            State.VoteContract.Vote.Send(new VoteInput
            {
                Voter        = Context.Sender,
                VotingItemId = State.MinerElectionVotingItemId.Value,
                Amount       = input.Amount,
                Option       = input.CandidatePubkey,
                VoteId       = Context.TransactionId
            });

            var votesWeight = GetVotesWeight(input.Amount, lockSeconds);

            State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
            {
                SchemeId         = State.WelfareHash.Value,
                BeneficiaryShare = new BeneficiaryShare
                {
                    Beneficiary = Context.Sender,
                    Shares      = votesWeight
                },
                EndPeriod = GetEndPeriod(lockSeconds)
            });

            var rankingList = State.DataCentersRankingList.Value;

            if (State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                rankingList.DataCenters[input.CandidatePubkey] =
                    rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount);
                State.DataCentersRankingList.Value = rankingList;
            }

            if (State.Candidates.Value.Value.Count > GetValidationDataCenterCount() &&
                !State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList);
            }

            return(new Empty());
        }