private void AddOrUpdateMinerHistoryInformation(CandidateInHistory historyInformation) { State.HistoryMap[historyInformation.PublicKey.ToStringValue()] = historyInformation; }
private ActionResult SnapshotForMiners(TermInfo input) { var lastRoundNumber = input.RoundNumber; var previousTermNumber = input.TermNumber; Assert(TryToGetRoundInformation(lastRoundNumber, out var roundInformation), "Round information not found."); foreach (var candidate in roundInformation.RealTimeMinersInformation) { CandidateInHistory candidateInHistory; if (TryToGetMinerHistoryInformation(candidate.Key, out var historyInformation)) { var terms = new List <long>(historyInformation.Terms.ToList()); if (terms.Contains(previousTermNumber)) { return(new ActionResult { Success = false, ErrorMessage = "Snapshot for miners in previous term already taken." }); } terms.Add(previousTermNumber); var continualAppointmentCount = historyInformation.ContinualAppointmentCount; if (TryToGetMiners(previousTermNumber, out var minersOfLastTerm) && minersOfLastTerm.PublicKeys.Contains(candidate.Key)) { continualAppointmentCount++; } else { continualAppointmentCount = 0; } candidateInHistory = new CandidateInHistory { PublicKey = candidate.Key, MissedTimeSlots = historyInformation.MissedTimeSlots + candidate.Value.MissedTimeSlots, ProducedBlocks = historyInformation.ProducedBlocks + candidate.Value.ProducedBlocks, ContinualAppointmentCount = continualAppointmentCount, ReappointmentCount = historyInformation.ReappointmentCount + 1, CurrentAlias = historyInformation.CurrentAlias, Terms = { terms } }; } else { candidateInHistory = new CandidateInHistory { PublicKey = candidate.Key, MissedTimeSlots = candidate.Value.MissedTimeSlots, ProducedBlocks = candidate.Value.ProducedBlocks, ContinualAppointmentCount = 0, ReappointmentCount = 0, Terms = { previousTermNumber } }; } AddOrUpdateMinerHistoryInformation(candidateInHistory); } return(new ActionResult { Success = true }); }
private bool TryToGetMinerHistoryInformation(string publicKey, out CandidateInHistory historyInformation) { historyInformation = State.HistoryMap[publicKey.ToStringValue()]; return(historyInformation != null); }
public override Empty NextTerm(Round input) { // Count missed time slot of current round. CountMissedTimeSlots(); Assert(TryToGetTermNumber(out var termNumber), "Term number not found."); // Update current term number and current round number. Assert(TryToUpdateTermNumber(input.TermNumber), "Failed to update term number."); Assert(TryToUpdateRoundNumber(input.RoundNumber), "Failed to update round number."); // Reset some fields of first two rounds of next term. foreach (var minerInRound in input.RealTimeMinersInformation.Values) { minerInRound.MissedTimeSlots = 0; minerInRound.ProducedBlocks = 0; } var senderPublicKey = Context.RecoverPublicKey().ToHex(); // Update produced block number of this node. if (input.RealTimeMinersInformation.ContainsKey(senderPublicKey)) { input.RealTimeMinersInformation[senderPublicKey].ProducedBlocks += 1; } else { if (TryToGetMinerHistoryInformation(senderPublicKey, out var historyInformation)) { historyInformation.ProducedBlocks += 1; } else { historyInformation = new CandidateInHistory { PublicKey = senderPublicKey, ProducedBlocks = 1, CurrentAlias = senderPublicKey.Substring(0, DPoSContractConsts.AliasLimit) }; } AddOrUpdateMinerHistoryInformation(historyInformation); } // Update miners list. Assert(SetMiners(input.RealTimeMinersInformation.Keys.ToList().ToMiners(input.TermNumber)), ContractErrorCode.GetErrorMessage(ContractErrorCode.AttemptFailed, "Failed to update miners list.")); // Update term number lookup. (Using term number to get first round number of related term.) State.TermToFirstRoundMap[input.TermNumber.ToInt64Value()] = input.RoundNumber.ToInt64Value(); // Update blockchain age of new term. UpdateBlockchainAge(input.BlockchainAge); // Update rounds information of next two rounds. Assert(TryToAddRoundInformation(input), "Failed to add round information."); if (State.DividendContract.Value != null) { State.DividendContract.Value = State.BasicContractZero.GetContractAddressByName.Call(State.DividendContractSystemName.Value); State.DividendContract.KeepWeights.Send(new SInt64Value { Value = termNumber }); var termInfo = new TermInfo { RoundNumber = input.RoundNumber - 1, TermNumber = input.TermNumber - 1 }; Assert(SnapshotForTerm(termInfo).Success, ContractErrorCode.GetErrorMessage(ContractErrorCode.AttemptFailed, $"Failed to take snapshot of term {termInfo.TermNumber}")); Assert(SnapshotForMiners(termInfo).Success, ContractErrorCode.GetErrorMessage(ContractErrorCode.AttemptFailed, $"Failed to take snapshot of miners of term {termInfo.TermNumber}")); Assert(SendDividends(termInfo).Success, ContractErrorCode.GetErrorMessage(ContractErrorCode.AttemptFailed, $"Failed to send dividends of term {termInfo.TermNumber}")); } Context.LogDebug(() => $"Changing term number to {input.TermNumber}"); TryToFindLIB(); return(new Empty()); }