/// <summary> /// AElf Consensus Behaviour is changeable in this method when /// this miner should skip his time slot more precisely. /// </summary> /// <param name="behaviour"></param> /// <param name="currentRound"></param> /// <param name="pubkey"></param> /// <param name="currentBlockTime"></param> /// <returns></returns> private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, Round currentRound, string pubkey, Timestamp currentBlockTime = null) { if (SolitaryMinerDetection(currentRound, pubkey)) { return(ConsensusCommandProvider.InvalidConsensusCommand); } if (currentRound.RoundNumber == 1 && behaviour != AElfConsensusBehaviour.TinyBlock) { return(new ConsensusCommandProvider(new FirstRoundCommandStrategy(currentRound, pubkey, currentBlockTime, behaviour)).GetConsensusCommand()); } Context.LogDebug(() => $"Params to get command: {behaviour}, {pubkey}, {currentBlockTime}"); switch (behaviour) { case AElfConsensusBehaviour.UpdateValue: TryToGetPreviousRoundInformation(out var previousRound); return(new ConsensusCommandProvider(new NormalBlockCommandStrategy(currentRound, pubkey, currentBlockTime, previousRound.RoundId)).GetConsensusCommand()); case AElfConsensusBehaviour.NextRound: case AElfConsensusBehaviour.NextTerm: return(new ConsensusCommandProvider( new TerminateRoundCommandStrategy(currentRound, pubkey, currentBlockTime, behaviour == AElfConsensusBehaviour.NextTerm)) .GetConsensusCommand()); case AElfConsensusBehaviour.TinyBlock: { var consensusCommand = new ConsensusCommandProvider(new TinyBlockCommandStrategy(currentRound, pubkey, currentBlockTime, GetMaximumBlocksCount())).GetConsensusCommand(); if (consensusCommand.Hint == new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.NextRound }.ToByteString()) { Context.LogDebug(() => "Re-arranged behaviour from TinyBlock to NextRound."); } return(consensusCommand); } default: return(ConsensusCommandProvider.InvalidConsensusCommand); } }
/// <summary> /// AElf Consensus Behaviour is changeable in this method when /// this miner should skip his time slot more precisely. /// </summary> /// <param name="behaviour"></param> /// <param name="currentRound"></param> /// <param name="publicKey"></param> /// <returns></returns> private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, Round currentRound, string publicKey) { if (SolitaryMinerDetection(currentRound, publicKey)) { return(ConsensusCommandProvider.InvalidConsensusCommand); } var currentBlockTime = Context.CurrentBlockTime; if (currentRound.RoundNumber == 1 && behaviour != AElfConsensusBehaviour.TinyBlock) { return(new ConsensusCommandProvider(new FirstRoundCommandStrategy(currentRound, publicKey, currentBlockTime, behaviour)).GetConsensusCommand()); } switch (behaviour) { case AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue: case AElfConsensusBehaviour.UpdateValue: return(new ConsensusCommandProvider(new NormalBlockCommandStrategy(currentRound, publicKey, currentBlockTime)).GetConsensusCommand()); case AElfConsensusBehaviour.NextRound: case AElfConsensusBehaviour.NextTerm: return(new ConsensusCommandProvider( new TerminateRoundCommandStrategy(currentRound, publicKey, currentBlockTime, behaviour == AElfConsensusBehaviour.NextTerm)) .GetConsensusCommand()); case AElfConsensusBehaviour.TinyBlock: { var consensusCommand = new ConsensusCommandProvider(new TinyBlockCommandStrategy(currentRound, publicKey, currentBlockTime, GetMaximumBlocksCount())).GetConsensusCommand(); if (consensusCommand.Hint == new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.NextRound }.ToByteString()) { Context.LogDebug(() => "Re-arranged behaviour from TinyBlock to NextRound."); } return(consensusCommand); } } return(ConsensusCommandProvider.InvalidConsensusCommand); }
public FirstRoundCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, AElfConsensusBehaviour consensusBehaviour) : base(currentRound, pubkey, currentBlockTime) { _consensusBehaviour = consensusBehaviour; }
/// <summary> /// AElf Consensus Behaviour is changeable in this method. /// It's the situation this miner should skip his time slot more precisely. /// </summary> /// <param name="behaviour"></param> /// <param name="currentRound"></param> /// <param name="publicKey"></param> /// <returns></returns> private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, Round currentRound, string publicKey) { var miningInterval = currentRound.GetMiningInterval(); while (true) { var isAlone = CheckLonelyMiner(publicKey); if (behaviour == AElfConsensusBehaviour.TinyBlock && isAlone && currentRound.RealTimeMinersInformation.Count > 2 // There are more than 1 miner possible to save him. ) { behaviour = AElfConsensusBehaviour.Nothing; } var currentBlockTime = Context.CurrentBlockTime; Timestamp expectedMiningTime; int nextBlockMiningLeftMilliseconds; switch (behaviour) { case AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue: GetScheduleForUpdateValueWithoutPreviousInValue(currentRound, publicKey, out nextBlockMiningLeftMilliseconds, out expectedMiningTime); break; case AElfConsensusBehaviour.UpdateValue: expectedMiningTime = currentRound.GetExpectedMiningTime(publicKey); nextBlockMiningLeftMilliseconds = (int)(expectedMiningTime - currentBlockTime).Milliseconds(); break; case AElfConsensusBehaviour.TinyBlock: GetScheduleForTinyBlock(currentRound, publicKey, out nextBlockMiningLeftMilliseconds, out expectedMiningTime); if (nextBlockMiningLeftMilliseconds < 0) { Context.LogDebug(() => "Next block mining left milliseconds is less than 0 for tiny block."); behaviour = AElfConsensusBehaviour.NextRound; continue; } break; case AElfConsensusBehaviour.NextRound: GetScheduleForNextRound(currentRound, publicKey, out nextBlockMiningLeftMilliseconds, out expectedMiningTime); break; case AElfConsensusBehaviour.NextTerm: expectedMiningTime = currentRound.ArrangeAbnormalMiningTime(publicKey, currentBlockTime); if (currentRound.RealTimeMinersInformation.Single(m => m.Value.IsExtraBlockProducer).Key != publicKey) { expectedMiningTime.AddMilliseconds(miningInterval); } nextBlockMiningLeftMilliseconds = (int)(expectedMiningTime - currentBlockTime).Milliseconds(); break; case AElfConsensusBehaviour.Nothing: return(GetInvalidConsensusCommand()); default: return(GetInvalidConsensusCommand()); } AdjustLimitMillisecondsOfMiningBlock(currentRound, publicKey, nextBlockMiningLeftMilliseconds, out var limitMillisecondsOfMiningBlock); var milliseconds = nextBlockMiningLeftMilliseconds; Context.LogDebug(() => $"NextBlockMiningLeftMilliseconds: {milliseconds}"); // Produce tiny blocks as fast as one can. if (behaviour == AElfConsensusBehaviour.TinyBlock) { nextBlockMiningLeftMilliseconds = AEDPoSContractConstants.MinimumIntervalOfProducingBlocks; } return(new ConsensusCommand { ExpectedMiningTime = expectedMiningTime, NextBlockMiningLeftMilliseconds = nextBlockMiningLeftMilliseconds < 0 ? 0 : nextBlockMiningLeftMilliseconds, LimitMillisecondsOfMiningBlock = isAlone ? currentRound.GetMiningInterval() : behaviour == AElfConsensusBehaviour.NextTerm ? miningInterval : limitMillisecondsOfMiningBlock, Hint = new AElfConsensusHint { Behaviour = behaviour }.ToByteString() }); } }