public void ByteString_FromHexString()
        {
            var hexString = HashHelper.ComputeFrom("hash").ToHex();
            var result    = ByteStringHelper.FromHexString(hexString);

            result.ShouldNotBe(null);
        }
Ejemplo n.º 2
0
 public override ElectorVote GetElectorVote(StringValue input)
 {
     return(State.ElectorVotes[input.Value] ?? new ElectorVote
     {
         Pubkey = ByteStringHelper.FromHexString(input.Value)
     });
 }
        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);
        }
Ejemplo n.º 4
0
        public override ElectorVote GetElectorVoteWithRecords(StringValue input)
        {
            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);
        }
Ejemplo n.º 5
0
 public override CandidateVote GetCandidateVote(StringValue input)
 {
     return(State.CandidateVotes[input.Value] ?? new CandidateVote
     {
         Pubkey = ByteStringHelper.FromHexString(input.Value)
     });
 }
        private AElfConsensusHeaderInformation GetConsensusExtraDataForNextRound(Round currentRound,
                                                                                 string pubkey, AElfConsensusTriggerInformation triggerInformation)
        {
            GenerateNextRoundInformation(currentRound, Context.CurrentBlockTime, out var nextRound);

            nextRound.ExtraBlockProducerOfPreviousRound = pubkey;

            if (!nextRound.RealTimeMinersInformation.Keys.Contains(pubkey))
            {
                return(new AElfConsensusHeaderInformation
                {
                    SenderPubkey = ByteStringHelper.FromHexString(pubkey),
                    Round = nextRound,
                    Behaviour = triggerInformation.Behaviour
                });
            }

            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
            {
                SenderPubkey = ByteStringHelper.FromHexString(pubkey),
                Round = nextRound,
                Behaviour = triggerInformation.Behaviour
            });
        }
        /// <summary>
        /// Update Candidate's Votes information.
        /// </summary>
        /// <param name="candidatePublicKey"></param>
        /// <param name="amount"></param>
        /// <param name="voteId"></param>
        private long UpdateCandidateInformation(string candidatePublicKey, long amount, Hash voteId)
        {
            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);
            }

            State.CandidateVotes[candidatePublicKey] = candidateVotes;

            return(candidateVotes.ObtainedActiveVotedVotesAmount);
        }
Ejemplo n.º 8
0
        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 <InvalidOperationException>(() => { blockHeader3.GetHash(); });
        }
Ejemplo n.º 9
0
        private void RecordMinedMinerListOfCurrentRound()
        {
            TryToGetCurrentRoundInformation(out var currentRound);

            State.MinedMinerListMap.Set(currentRound.RoundNumber, new MinerList
            {
                Pubkeys = { currentRound.GetMinedMiners().Select(m => ByteStringHelper.FromHexString(m.Pubkey)) }
            });
        }
        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));
        }
Ejemplo n.º 11
0
        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)
            });
        }
Ejemplo n.º 12
0
        private static int CompareAddress(Address address1, Address address2)
        {
            if (address1 != null)
            {
                return(address2 == null ? 1 : ByteStringHelper.Compare(address1.Value, address2.Value));
            }

            if (address2 == null)
            {
                return(0);
            }

            return(-1);
        }
Ejemplo n.º 13
0
Archivo: Hash.cs Proyecto: zhxymh/AElf
        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);
        }
Ejemplo n.º 14
0
        private void UpdateCandidateInformation(string pubkey, long lastTermNumber,
                                                List <string> 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;
        }
        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
            });
        }
        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
            });
        }
Ejemplo n.º 17
0
        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");
        }
Ejemplo n.º 18
0
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var peerPool       = context.ServiceProvider.GetRequiredService <IPeerPool>();
            var accountService = context.ServiceProvider.GetRequiredService <IAccountService>();
            var pubkey         = AsyncHelper.RunSync(accountService.GetPublicKeyAsync).ToHex();

            {
                var peerWithNoNode = new Mock <IPeer>();
                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 <int>()))
                .Returns(Task.FromResult(new NodeList()));

                peerPool.TryAddPeer(peerWithNoNode.Object);
            }

            {
                var peerWithUnavailableNode = new Mock <IPeer>();
                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 <int>()))
                .Returns(Task.FromResult(new NodeList
                {
                    Nodes =
                    {
                        new NodeInfo
                        {
                            Endpoint = "192.168.100.100:8001",
                            Pubkey   = ByteString.CopyFromUtf8("192.168.100.100:8001")
                        }
                    }
                }));

                peerPool.TryAddPeer(peerWithUnavailableNode.Object);
            }

            {
                var peerWittSamePubkeyNode = new Mock <IPeer>();
                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 <int>()))
                .Returns(Task.FromResult(new NodeList
                {
                    Nodes =
                    {
                        new NodeInfo
                        {
                            Endpoint = "192.168.100.100:8002",
                            Pubkey   = ByteStringHelper.FromHexString(pubkey)
                        }
                    }
                }));

                peerPool.TryAddPeer(peerWittSamePubkeyNode.Object);
            }

            {
                var peerWithNormalNode = new Mock <IPeer>();
                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 <int>()))
                .Returns(Task.FromResult(new NodeList
                {
                    Nodes =
                    {
                        new NodeInfo
                        {
                            Endpoint = "192.168.100.100:8003",
                            Pubkey   = ByteString.CopyFromUtf8("192.168.100.100:8003")
                        }
                    }
                }));

                peerPool.TryAddPeer(peerWithNormalNode.Object);
            }
        }
Ejemplo n.º 19
0
        public async Task AEDPoSContract_ChangeMinersCount_Test()
        {
            const int termIntervalMin = 31536000 / 60;

            var maxCount = ValidationDataCenterKeyPairs.Count;

            await InitializeCandidates(maxCount);

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

            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 voter = GetElectionContractTester(VoterKeyPairs[0]);

            foreach (var candidateKeyPair in ValidationDataCenterKeyPairs)
            {
                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))
            {
                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();

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

                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++;
            }
        }
        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.");

            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 (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(() => "Failed to produce block at previous round?");
                        previousInValue = Hash.Empty;
                    }
                    else
                    {
                        previousInValue = triggerInformation.PreviousInValue;
                    }
                    signature = previousRound.CalculateSignature(triggerInformation.PreviousInValue);
                }
                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;
                        }

                        Context.LogDebug(() => $"TEST:\n{previousRound.ToString(pubkey)}\nInValue: {fakePreviousInValue}");
                        signature = previousRound.CalculateSignature(fakePreviousInValue);
                    }
                    else
                    {
                        // This miner appears first time in current round, like as a replacement of evil miner.
                        signature = previousRound.CalculateSignature(fakePreviousInValue);
                    }
                }
            }

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