Skip to content

Commit

Permalink
Merge pull request #2181 from AElfProject/fix/random
Browse files Browse the repository at this point in the history
Remove cache from consensus contract
  • Loading branch information
Peng Rong authored Nov 26, 2019
2 parents 2fafab8 + 4f6d4f5 commit c111608
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace AElf.Contracts.Consensus.AEDPoS
/// </summary>
public partial class AEDPoSContract
{
private readonly Dictionary<long, Round> _rounds = new Dictionary<long, Round>();
private string _processingBlockMinerPubkey;
private bool? _isMainChain;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public override SInt32Value GetMaximumBlocksCount(Empty input)
/// <returns></returns>
private int GetMaximumBlocksCount()
{
TryToGetCurrentRoundInformation(out var currentRound, true);
TryToGetCurrentRoundInformation(out var currentRound);
var libRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber;
var libBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight;
var currentHeight = Context.CurrentHeight;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,53 +45,27 @@ private bool TryToGetRoundNumber(out long roundNumber)
return roundNumber != 0;
}

private bool TryToGetCurrentRoundInformation(out Round round, bool useCache = false)
private bool TryToGetCurrentRoundInformation(out Round round)
{
round = null;
if (!TryToGetRoundNumber(out var roundNumber)) return false;

if (useCache && _rounds.ContainsKey(roundNumber))
{
round = _rounds[roundNumber];
}
else
{
round = State.Rounds[roundNumber];
}

round = State.Rounds[roundNumber];
return !round.IsEmpty;
}

private bool TryToGetPreviousRoundInformation(out Round previousRound, bool useCache = false)
private bool TryToGetPreviousRoundInformation(out Round previousRound)
{
previousRound = new Round();
if (!TryToGetRoundNumber(out var roundNumber)) return false;
if (roundNumber < 2) return false;
var targetRoundNumber = roundNumber.Sub(1);
if (useCache && _rounds.ContainsKey(targetRoundNumber))
{
previousRound = _rounds[targetRoundNumber];
}
else
{
previousRound = State.Rounds[targetRoundNumber];
}

previousRound = State.Rounds[targetRoundNumber];
return !previousRound.IsEmpty;
}

private bool TryToGetRoundInformation(long roundNumber, out Round round, bool useCache = false)
private bool TryToGetRoundInformation(long roundNumber, out Round round)
{
if (useCache && _rounds.ContainsKey(roundNumber))
{
round = _rounds[roundNumber];
}
else
{
round = State.Rounds[roundNumber];
_rounds[roundNumber] = round;
}

round = State.Rounds[roundNumber];
return !round.IsEmpty;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin
// Make sure the method GetMaximumBlocksCount executed no matter what consensus behaviour is.
var minersCountInTheory = GetMaximumBlocksCount();
ResetLatestProviderToTinyBlocksCount(minersCountInTheory);
ClearCachedFields();

// Clear cache.
_processingBlockMinerPubkey = null;
}

private void ProcessNextRound(Round nextRound)
{
RecordMinedMinerListOfCurrentRound();

TryToGetCurrentRoundInformation(out var currentRound, true);
TryToGetCurrentRoundInformation(out var currentRound);

// Do some other stuff during the first time to change round.
if (currentRound.RoundNumber == 1)
Expand Down Expand Up @@ -97,7 +99,7 @@ private void ProcessNextRound(Round nextRound)
Context.LogDebug(() => "Evil miners detected.");
foreach (var evilMiner in evilMiners)
{
Context.LogDebug(() =>
Context.LogDebug(() =>
$"Evil miner {evilMiner}, missed time slots: {currentRound.RealTimeMinersInformation[evilMiner].MissedTimeSlots}.");
// Mark these evil miners.
State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput
Expand Down Expand Up @@ -191,7 +193,7 @@ private void RecordMinedMinerListOfCurrentRound()

private void ProcessUpdateValue(UpdateValueInput updateValueInput)
{
TryToGetCurrentRoundInformation(out var currentRound, true);
TryToGetCurrentRoundInformation(out var currentRound);

var minerInRound = currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey];
minerInRound.ActualMiningTimes.Add(updateValueInput.ActualMiningTime);
Expand Down Expand Up @@ -259,7 +261,11 @@ private static void PerformSecretSharing(UpdateValueInput input, MinerInRound mi

private void ProcessTinyBlock(TinyBlockInput tinyBlockInput)
{
TryToGetCurrentRoundInformation(out var currentRound, true);
TryToGetCurrentRoundInformation(out var currentRound);

Context.LogDebug(() =>
$"Processing tiny block:\n {currentRound}\n" +
$"Current height: {Context.CurrentHeight}\nPrevious block hash: {Context.PreviousBlockHash.ToHex()}");

currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey].ActualMiningTimes
.Add(tinyBlockInput.ActualMiningTime);
Expand Down Expand Up @@ -334,11 +340,5 @@ private void ResetLatestProviderToTinyBlocksCount(int minersCountInTheory)
}
}
}

private void ClearCachedFields()
{
_rounds.Clear();
_processingBlockMinerPubkey = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Acs4;
using Google.Protobuf.WellKnownTypes;

namespace AElf.Contracts.Consensus.AEDPoS
{
Expand All @@ -13,33 +14,32 @@ public partial class AEDPoSContract
/// <returns></returns>
private ValidationResult ValidateBeforeExecution(AElfConsensusHeaderInformation extraData)
{
Context.LogDebug(extraData.ToString);

// According to current round information:
if (!TryToGetCurrentRoundInformation(out var baseRound))
{
return new ValidationResult {Success = false, Message = "Failed to get current round information."};
}

var providedRound = extraData.Round;
if (extraData.Behaviour == AElfConsensusBehaviour.UpdateValue)
{
providedRound = baseRound.RecoverFromUpdateValue(extraData.Round, extraData.SenderPubkey.ToHex());
baseRound.RecoverFromUpdateValue(extraData.Round, extraData.SenderPubkey.ToHex());
}

if (extraData.Behaviour == AElfConsensusBehaviour.TinyBlock)
{
providedRound = baseRound.RecoverFromTinyBlock(extraData.Round, extraData.SenderPubkey.ToHex());
baseRound.RecoverFromTinyBlock(extraData.Round, extraData.SenderPubkey.ToHex());
}

var validationContext = new ConsensusValidationContext
{
BaseRound = baseRound,
CurrentTermNumber = State.CurrentTermNumber.Value,
CurrentRoundNumber = State.CurrentRoundNumber.Value,
Rounds = State.Rounds,
PreviousRound = TryToGetPreviousRoundInformation(out var previousRound) ? previousRound : new Round(),
LatestProviderToTinyBlocksCount = State.LatestProviderToTinyBlocksCount.Value,
ExtraData = extraData,
RoundsDict = _rounds,
ProvidedRound = providedRound
ExtraData = extraData
};

/* Ask several questions: */
Expand All @@ -54,16 +54,15 @@ private ValidationResult ValidateBeforeExecution(AElfConsensusHeaderInformation
new TimeSlotValidationProvider(),

// Is sender produced too many blocks at one time?
new ContinuousBlocksValidationProvider(),

// Is confirmed lib height and lib round number went down? (Which should not happens.)
new LibInformationValidationProvider(),
new ContinuousBlocksValidationProvider()
};

switch (extraData.Behaviour)
{
case AElfConsensusBehaviour.UpdateValue:
validationProviders.Add(new UpdateValueValidationProvider());
// Is confirmed lib height and lib round number went down? (Which should not happens.)
validationProviders.Add(new LibInformationValidationProvider());
break;
case AElfConsensusBehaviour.NextRound:
// Is sender's order of next round correct?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public class ConsensusValidationContext
/// <summary>
/// This validation focuses on the new round information.
/// </summary>
public Round ProvidedRound { get; set; }
public Round ProvidedRound => ExtraData.Round;

public Round PreviousRound { get; set; }

public Dictionary<long, Round> RoundsDict { get; set; }
public MappedState<long, Round> Rounds { get; set; }
public LatestProviderToTinyBlocksCount LatestProviderToTinyBlocksCount { get; set; }
public AElfConsensusHeaderInformation ExtraData { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ public ValidationResult ValidateHeaderInformation(ConsensusValidationContext val
var baseRound = validationContext.BaseRound;
var providedRound = validationContext.ProvidedRound;
var pubkey = validationContext.SenderPubkey;
if (baseRound.ConfirmedIrreversibleBlockHeight > providedRound.ConfirmedIrreversibleBlockHeight ||
baseRound.ConfirmedIrreversibleBlockRoundNumber > providedRound.ConfirmedIrreversibleBlockRoundNumber)
if (providedRound.ConfirmedIrreversibleBlockHeight != 0 &&
providedRound.ConfirmedIrreversibleBlockRoundNumber != 0 &&
(baseRound.ConfirmedIrreversibleBlockHeight > providedRound.ConfirmedIrreversibleBlockHeight ||
baseRound.ConfirmedIrreversibleBlockRoundNumber > providedRound.ConfirmedIrreversibleBlockRoundNumber))
{
validationResult.Message = "Incorrect lib information.";
validationResult.Message = $"Incorrect lib information.\n" +
$"{baseRound.ConfirmedIrreversibleBlockHeight} > {providedRound.ConfirmedIrreversibleBlockHeight}\n" +
$"{baseRound.ConfirmedIrreversibleBlockRoundNumber} > {providedRound.ConfirmedIrreversibleBlockRoundNumber}";
return validationResult;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@ public ValidationResult ValidateHeaderInformation(ConsensusValidationContext val

private bool IsRoundIdMatched(ConsensusValidationContext validationContext)
{
if (TryToGetCurrentRoundInformation(out var currentRound, validationContext))
{
return currentRound.RoundId == validationContext.ProvidedRound.RoundIdForValidation;
}

return false;
return validationContext.BaseRound.RoundId == validationContext.ProvidedRound.RoundIdForValidation;
}

private bool ValidateProducedBlocksCount(ConsensusValidationContext validationContext)
Expand All @@ -37,30 +32,5 @@ private bool ValidateProducedBlocksCount(ConsensusValidationContext validationCo
return validationContext.BaseRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1) ==
validationContext.ProvidedRound.RealTimeMinersInformation[pubkey].ProducedBlocks;
}

private bool TryToGetCurrentRoundInformation(out Round round, ConsensusValidationContext validationContext,
bool useCache = false)
{
round = null;
var rounds = validationContext.RoundsDict;
if (!TryToGetRoundNumber(out var roundNumber, validationContext.CurrentRoundNumber)) return false;

if (useCache && rounds.ContainsKey(roundNumber))
{
round = rounds[roundNumber];
}
else
{
round = validationContext.Rounds[roundNumber];
}

return !round.IsEmpty;
}

private bool TryToGetRoundNumber(out long roundNumber, long currentRoundNumber)
{
roundNumber = currentRoundNumber;
return roundNumber != 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,14 @@ private ValidationResult ValidationForNextRound(ConsensusValidationContext valid
// Round Number
// In Values Should Be Null
var extraData = validationContext.ExtraData;
if (TryToGetCurrentRoundInformation(out var currentRound, validationContext, true) &&
currentRound.RoundNumber.Add(1) != extraData.Round.RoundNumber)
if (validationContext.BaseRound.RoundNumber.Add(1) != extraData.Round.RoundNumber)
{
return new ValidationResult {Message = "Incorrect round number for next round."};
}

if (extraData.Round.RealTimeMinersInformation.Values.Any(m => m.InValue != null))
{
return new ValidationResult {Message = "Incorrect next round information."};
}

return new ValidationResult {Success = true};
return extraData.Round.RealTimeMinersInformation.Values.Any(m => m.InValue != null)
? new ValidationResult {Message = "Incorrect next round information."}
: new ValidationResult {Success = true};
}

private ValidationResult ValidationForNextTerm(ConsensusValidationContext validationContext)
Expand All @@ -56,38 +52,9 @@ private ValidationResult ValidationForNextTerm(ConsensusValidationContext valida

// Is next term information correct?
// Term Number
if (TryToGetCurrentRoundInformation(out var currentRound, validationContext, true) &&
currentRound.TermNumber.Add(1) != extraData.Round.TermNumber)
{
return new ValidationResult {Message = "Incorrect term number for next round."};
}

return new ValidationResult {Success = true};
}

private bool TryToGetCurrentRoundInformation(out Round round, ConsensusValidationContext validationContext,
bool useCache = false)
{
round = null;
var rounds = validationContext.RoundsDict;
if (!TryToGetRoundNumber(out var roundNumber, validationContext.CurrentRoundNumber)) return false;

if (useCache && rounds.ContainsKey(roundNumber))
{
round = rounds[roundNumber];
}
else
{
round = validationContext.Rounds[roundNumber];
}

return !round.IsEmpty;
}

private bool TryToGetRoundNumber(out long roundNumber, long currentRoundNumber)
{
roundNumber = currentRoundNumber;
return roundNumber != 0;
return validationContext.BaseRound.TermNumber.Add(1) != extraData.Round.TermNumber
? new ValidationResult {Message = "Incorrect term number for next round."}
: new ValidationResult {Success = true};
}
}
}
Loading

0 comments on commit c111608

Please sign in to comment.