public override Empty ChangeVotingOption(ChangeVotingOptionInput 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, "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 oldCandidateVotes = State.CandidateVotes[votingRecord.Option];

            oldCandidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId);
            oldCandidateVotes.ObtainedActiveVotedVotesAmount =
                oldCandidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount);
            State.CandidateVotes[votingRecord.Option] = oldCandidateVotes;

            var newCandidateVotes = State.CandidateVotes[input.CandidatePubkey];

            if (newCandidateVotes != null)
            {
                newCandidateVotes.ObtainedActiveVotingRecordIds.Add(input.VoteId);
                newCandidateVotes.ObtainedActiveVotedVotesAmount =
                    newCandidateVotes.ObtainedActiveVotedVotesAmount.Add(votingRecord.Amount);
                State.CandidateVotes[input.CandidatePubkey] = newCandidateVotes;
            }
            else
            {
                State.CandidateVotes[input.CandidatePubkey] = new CandidateVote
                {
                    Pubkey = input.CandidatePubkey.ToByteString(),
                    ObtainedActiveVotingRecordIds  = { input.VoteId },
                    ObtainedActiveVotedVotesAmount = votingRecord.Amount,
                    AllObtainedVotedVotesAmount    = votingRecord.Amount
                };
            }
            return(new Empty());
        }
        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 oldCandidateVotes = State.CandidateVotes[votingRecord.Option];

            oldCandidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId);
            oldCandidateVotes.ObtainedActiveVotedVotesAmount =
                oldCandidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount);
            oldCandidateVotes.AllObtainedVotedVotesAmount =
                oldCandidateVotes.AllObtainedVotedVotesAmount.Sub(votingRecord.Amount);
            State.CandidateVotes[votingRecord.Option] = oldCandidateVotes;

            var voteAmountOfNewCandidate = 0L;
            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 dataCenterList = State.DataCentersRankingList.Value;

            if (dataCenterList.DataCenters.ContainsKey(input.CandidatePubkey))
            {
                dataCenterList.DataCenters[input.CandidatePubkey] =
                    dataCenterList.DataCenters[input.CandidatePubkey].Add(votingRecord.Amount);
            }
            else
            {
                IsCandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate);
            }
            if (dataCenterList.DataCenters.ContainsKey(votingRecord.Option))
            {
                dataCenterList.DataCenters[votingRecord.Option] =
                    dataCenterList.DataCenters[votingRecord.Option].Sub(votingRecord.Amount);
                IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, votingRecord.Option);
            }

            State.DataCentersRankingList.Value = dataCenterList;
            return(new Empty());
        }