示例#1
0
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            var validationResult = new ValidationResult();

            // If provided round is a new round
            if (validationContext.ProvidedRound.RoundId != validationContext.BaseRound.RoundId)
            {
                // Is new round information fits time slot rule?
                validationResult = validationContext.ProvidedRound.CheckRoundTimeSlots();
                if (!validationResult.Success)
                {
                    return(validationResult);
                }
            }
            else
            {
                // Is sender respect his time slot?
                // It is maybe failing due to using too much time producing previous tiny blocks.
                if (!CheckMinerTimeSlot(validationContext))
                {
                    validationResult.Message =
                        $"Time slot already passed before execution.{validationContext.SenderPubkey}";
                    validationResult.IsReTrigger = true;
                    return(validationResult);
                }
            }

            validationResult.Success = true;
            return(validationResult);
        }
        private bool ValidatePreviousInValue(ConsensusValidationContext validationContext)
        {
            var extraData = validationContext.ExtraData;
            var publicKey = validationContext.SenderPubkey;

            if (!validationContext.PreviousRound.RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(true);
            }

            if (extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue == null)
            {
                return(true);
            }

            var previousOutValue = validationContext.PreviousRound.RealTimeMinersInformation[publicKey].OutValue;
            var previousInValue  = extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue;

            if (previousInValue == Hash.Empty)
            {
                return(true);
            }

            return(Hash.FromMessage(previousInValue) == previousOutValue);
        }
示例#3
0
        private bool CheckMinerTimeSlot(ConsensusValidationContext validationContext)
        {
            if (IsFirstRoundOfCurrentTerm(out _, validationContext))
            {
                return(true);
            }
            var minerInRound           = validationContext.BaseRound.RealTimeMinersInformation[validationContext.SenderPubkey];
            var latestActualMiningTime = minerInRound.ActualMiningTimes.OrderBy(t => t).LastOrDefault();

            if (latestActualMiningTime == null)
            {
                return(true);
            }
            var expectedMiningTime    = minerInRound.ExpectedMiningTime;
            var endOfExpectedTimeSlot =
                expectedMiningTime.AddMilliseconds(validationContext.BaseRound.GetMiningInterval());

            if (latestActualMiningTime < expectedMiningTime)
            {
                // Which means this miner is producing tiny blocks for previous extra block slot.
                return(latestActualMiningTime < validationContext.BaseRound.GetRoundStartTime());
            }

            return(latestActualMiningTime < endOfExpectedTimeSlot);
        }
示例#4
0
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            var validationResult = new ValidationResult();
            var baseRound        = validationContext.BaseRound;
            var providedRound    = validationContext.ProvidedRound;
            var pubkey           = validationContext.SenderPubkey;

            if (providedRound.ConfirmedIrreversibleBlockHeight != 0 &&
                providedRound.ConfirmedIrreversibleBlockRoundNumber != 0 &&
                (baseRound.ConfirmedIrreversibleBlockHeight > providedRound.ConfirmedIrreversibleBlockHeight ||
                 baseRound.ConfirmedIrreversibleBlockRoundNumber > providedRound.ConfirmedIrreversibleBlockRoundNumber))
            {
                validationResult.Message = "Incorrect lib information.\n" +
                                           $"{baseRound.ConfirmedIrreversibleBlockHeight} > {providedRound.ConfirmedIrreversibleBlockHeight}\n" +
                                           $"{baseRound.ConfirmedIrreversibleBlockRoundNumber} > {providedRound.ConfirmedIrreversibleBlockRoundNumber}";
                return(validationResult);
            }

            if (providedRound.RealTimeMinersInformation.ContainsKey(pubkey) &&
                providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight != 0 &&
                baseRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight >
                providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight)
            {
                validationResult.Message = "Incorrect implied lib height.";
                return(validationResult);
            }

            validationResult.Success = true;
            return(validationResult);
        }
        private bool ValidateProducedBlocksCount(ConsensusValidationContext validationContext)
        {
            var pubkey = validationContext.SenderPubkey;

            return(validationContext.BaseRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1) ==
                   validationContext.ProvidedRound.RealTimeMinersInformation[pubkey].ProducedBlocks);
        }
        /// <summary>
        /// Check only one Out Value was filled during this updating.
        /// </summary>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        private bool NewConsensusInformationFilled(ConsensusValidationContext validationContext)
        {
            var minerInRound =
                validationContext.ProvidedRound.RealTimeMinersInformation[validationContext.SenderPubkey];

            return(minerInRound.OutValue != null && minerInRound.Signature != null &&
                   minerInRound.OutValue.Value.Any() && minerInRound.Signature.Value.Any());
        }
        /// <summary>
        /// This validation will based on current round information stored in StateDb.
        /// Simply check keys of RealTimeMinersInformation should be enough.
        /// </summary>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            var validationResult = new ValidationResult();

            if (!validationContext.BaseRound.RealTimeMinersInformation.Keys.Contains(validationContext.SenderPubkey))
            {
                validationResult.Message = $"Sender {validationContext.SenderPubkey} is not a miner.";
                return(validationResult);
            }

            validationResult.Success = true;
            return(validationResult);
        }
示例#8
0
        public ValidationResult ValidateInformation(ConsensusValidationContext validationContext)
        {
            foreach (var headerInformationValidationProvider in _headerInformationValidationProviders)
            {
                var result =
                    headerInformationValidationProvider.ValidateHeaderInformation(validationContext);
                if (!result.Success)
                {
                    return(result);
                }
            }

            return(new ValidationResult {
                Success = true
            });
        }
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            // Miners that have determined the order of the next round should be equal to
            // miners that mined blocks during current round.
            var validationResult = new ValidationResult();
            var providedRound    = validationContext.ProvidedRound;

            if (providedRound.RealTimeMinersInformation.Values.Where(m => m.FinalOrderOfNextRound > 0).Distinct()
                .Count() != providedRound.RealTimeMinersInformation.Values.Count(m => m.OutValue != null))
            {
                validationResult.Message = "Invalid FinalOrderOfNextRound.";
                return(validationResult);
            }

            validationResult.Success = true;
            return(validationResult);
        }
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            var validationResult = new ValidationResult();
            var extraData        = validationContext.ExtraData;

            switch (extraData.Behaviour)
            {
            case AElfConsensusBehaviour.NextRound:
                return(ValidationForNextRound(validationContext));

            case AElfConsensusBehaviour.NextTerm:
                return(ValidationForNextTerm(validationContext));

            default:
                validationResult.Success = true;
                return(validationResult);
            }
        }
        private ValidationResult ValidationForNextTerm(ConsensusValidationContext validationContext)
        {
            var extraData        = validationContext.ExtraData;
            var validationResult = ValidationForNextRound(validationContext);

            if (!validationResult.Success)
            {
                return(validationResult);
            }

            // Is next term number correct?
            return(validationContext.BaseRound.TermNumber.Add(1) != extraData.Round.TermNumber
                ? new ValidationResult {
                Message = "Incorrect term number for next round."
            }
                : new ValidationResult {
                Success = true
            });
        }
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            // Only one Out Value should be filled.
            if (!NewConsensusInformationFilled(validationContext))
            {
                return(new ValidationResult {
                    Message = "Incorrect new Out Value."
                });
            }

            if (!ValidatePreviousInValue(validationContext))
            {
                return(new ValidationResult {
                    Message = "Incorrect previous in value."
                });
            }

            return(new ValidationResult {
                Success = true
            });
        }
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            // Need to check round id when updating current round information.
            if (!IsRoundIdMatched(validationContext))
            {
                return(new ValidationResult {
                    Message = "Round Id not match."
                });
            }

            if (!ValidateProducedBlocksCount(validationContext))
            {
                return(new ValidationResult {
                    Message = "Incorrect produced blocks count."
                });
            }

            return(new ValidationResult {
                Success = true
            });
        }
        public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext)
        {
            // Is sender produce too many continuous blocks?
            var validationResult = new ValidationResult();

            if (validationContext.ProvidedRound.RoundNumber > 2 && // Skip first two rounds.
                validationContext.BaseRound.RealTimeMinersInformation.Count != 1)
            {
                var latestPubkeyToTinyBlocksCount = validationContext.LatestPubkeyToTinyBlocksCount;
                if (latestPubkeyToTinyBlocksCount != null &&
                    latestPubkeyToTinyBlocksCount.Pubkey == validationContext.SenderPubkey &&
                    latestPubkeyToTinyBlocksCount.BlocksCount < 0)
                {
                    validationResult.Message = "Sender produced too many continuous blocks.";
                    return(validationResult);
                }
            }

            validationResult.Success = true;
            return(validationResult);
        }
        private ValidationResult ValidationForNextRound(ConsensusValidationContext validationContext)
        {
            // Is next round information correct?
            // Currently two aspects:
            //   Round Number
            //   In Values Should Be Null
            var extraData = validationContext.ExtraData;

            if (validationContext.BaseRound.RoundNumber.Add(1) != extraData.Round.RoundNumber)
            {
                return(new ValidationResult {
                    Message = "Incorrect round number for next round."
                });
            }

            return(extraData.Round.RealTimeMinersInformation.Values.Any(m => m.InValue != null)
                ? new ValidationResult {
                Message = "Incorrect next round information."
            }
                : new ValidationResult {
                Success = true
            });
        }
示例#16
0
 private bool IsFirstRoundOfCurrentTerm(out long termNumber, ConsensusValidationContext validationContext)
 {
     termNumber = validationContext.CurrentTermNumber;
     return(validationContext.PreviousRound.TermNumber != termNumber ||
            validationContext.CurrentRoundNumber == 1);
 }
 private bool IsRoundIdMatched(ConsensusValidationContext validationContext)
 {
     return(validationContext.BaseRound.RoundId == validationContext.ProvidedRound.RoundIdForValidation);
 }