public AElfConsensusBehaviour GetConsensusBehaviour() { if (!CurrentRound.IsInMinerList(Pubkey)) { return(AElfConsensusBehaviour.Nothing); } if (!MinerInRound.IsThisANewRoundForThisMiner()) { var behaviour = HandleMinerInNewRound(); if (behaviour != AElfConsensusBehaviour.Nothing) { return(behaviour); } } else if (!IsTimeSlotPassed) { if (MinerInRound.ProducedTinyBlocks < MaximumBlocksCount) { return(AElfConsensusBehaviour.TinyBlock); } var blocksBeforeCurrentRound = MinerInRound.ActualMiningTimes.Count(t => t < CurrentRound.GetRoundStartTime()); if (CurrentRound.ExtraBlockProducerOfPreviousRound == Pubkey && !CurrentRound.IsMinerListJustChanged && MinerInRound.ProducedTinyBlocks < MaximumBlocksCount.Add(blocksBeforeCurrentRound)) { return(AElfConsensusBehaviour.TinyBlock); } } return(GetConsensusBehaviourToTerminateCurrentRound()); }
public AElfConsensusBehaviour GetConsensusBehaviour() { // The most simple situation: provided pubkey isn't a miner. if (!CurrentRound.IsInMinerList(_pubkey)) { return(AElfConsensusBehaviour.Nothing); } // If out value is null, it means provided pubkey hasn't mine any block during current round period. if (_minerInRound.OutValue == null) { var behaviour = HandleMinerInNewRound(); // It's possible HandleMinerInNewRound can't handle all the situations, if this method returns Nothing, // just go ahead. Otherwise, return it's result. if (behaviour != AElfConsensusBehaviour.Nothing) { return(behaviour); } } else if (!_isTimeSlotPassed ) // Provided pubkey mined blocks during current round, and current block time is still in his time slot. { if (_minerInRound.ActualMiningTimes.Count < _maximumBlocksCount) { // Provided pubkey can keep producing tiny blocks. return(AElfConsensusBehaviour.TinyBlock); } var blocksBeforeCurrentRound = _minerInRound.ActualMiningTimes.Count(t => t <= CurrentRound.GetRoundStartTime()); // If provided pubkey is the one who terminated previous round, he can mine // (_maximumBlocksCount + blocksBeforeCurrentRound) blocks // because he has two time slots recorded in current round. if (CurrentRound.ExtraBlockProducerOfPreviousRound == _pubkey && // Provided pubkey terminated previous round !CurrentRound.IsMinerListJustChanged && // & Current round isn't the first round of current term _minerInRound.ActualMiningTimes.Count.Add(1) < _maximumBlocksCount.Add( blocksBeforeCurrentRound) // & Provided pubkey hasn't mine enough blocks for current round. ) { // Then provided pubkey can keep producing tiny blocks. return(AElfConsensusBehaviour.TinyBlock); } } return(GetConsensusBehaviourToTerminateCurrentRound()); }
private bool CheckMinerTimeSlot(Round round, string publicKey) { if (IsFirstRoundOfCurrentTerm(out _)) { return(true); } var minerInRound = round.RealTimeMinersInformation[publicKey]; var latestActualMiningTime = minerInRound.ActualMiningTimes.OrderBy(t => t).LastOrDefault(); if (latestActualMiningTime == null) { return(true); } var expectedMiningTime = minerInRound.ExpectedMiningTime; var endOfExpectedTimeSlot = expectedMiningTime.AddMilliseconds(round.GetMiningInterval()); if (latestActualMiningTime < expectedMiningTime) { // Which means this miner is producing tiny blocks for previous extra block slot. Context.LogDebug(() => $"latest actual mining time: {latestActualMiningTime}, round start time: {round.GetRoundStartTime()}"); return(latestActualMiningTime < round.GetRoundStartTime()); } Context.LogDebug(() => $"latest actual mining time: {latestActualMiningTime}, end of expected mining time: {endOfExpectedTimeSlot}"); return(latestActualMiningTime < endOfExpectedTimeSlot); }