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