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());
            }
Exemple #3
0
        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);
        }