Beispiel #1
0
        /// <summary>
        /// Slash the validator with index ``slashed_index``.
        /// </summary>
        public void SlashValidator(BeaconState state, ValidatorIndex slashedIndex, ValidatorIndex whistleblowerIndex)
        {
            var rewardsAndPenalties = _rewardsAndPenaltiesOptions.CurrentValue;
            var stateListLengths    = _stateListLengthOptions.CurrentValue;

            var epoch = _beaconStateAccessor.GetCurrentEpoch(state);

            InitiateValidatorExit(state, slashedIndex);
            var validator = state.Validators[(int)(ulong)slashedIndex];

            validator.SetSlashed();
            var slashedWithdrawableEpoch = epoch + stateListLengths.EpochsPerSlashingsVector;
            var withdrawableEpoch        = Epoch.Max(validator.WithdrawableEpoch, slashedWithdrawableEpoch);

            validator.SetWithdrawableEpoch(withdrawableEpoch);

            var slashingsIndex = epoch % stateListLengths.EpochsPerSlashingsVector;

            state.SetSlashings(slashingsIndex, validator.EffectiveBalance);
            var slashingPenalty = validator.EffectiveBalance / rewardsAndPenalties.MinimumSlashingPenaltyQuotient;

            DecreaseBalance(state, slashedIndex, slashingPenalty);

            // Apply proposer and whistleblower rewards
            var proposerIndex = _beaconStateAccessor.GetBeaconProposerIndex(state);

            if (whistleblowerIndex == ValidatorIndex.None)
            {
                whistleblowerIndex = proposerIndex;
            }
            var whistleblowerReward = validator.EffectiveBalance / rewardsAndPenalties.WhistleblowerRewardQuotient;
            var proposerReward      = whistleblowerReward / rewardsAndPenalties.ProposerRewardQuotient;

            IncreaseBalance(state, proposerIndex, proposerReward);
            IncreaseBalance(state, whistleblowerIndex, whistleblowerReward - proposerReward);
        }
        public void ProcessAttestation(BeaconState state, Attestation attestation)
        {
            _logger.LogInformation(Event.ProcessAttestation, "Process block operation attestation {Attestation} for state {BeaconState}.", attestation, state);

            var timeParameters = _timeParameterOptions.CurrentValue;
            var data           = attestation.Data;

            var committeeCount = _beaconStateAccessor.GetCommitteeCountAtSlot(state, data.Slot);

            if ((ulong)data.Index >= committeeCount)
            {
                throw new ArgumentOutOfRangeException("attestation.Data.Index", data.Index, $"Attestation data committee index must be less that the committee count {committeeCount}.");
            }
            var previousEpoch = _beaconStateAccessor.GetPreviousEpoch(state);
            var currentEpoch  = _beaconStateAccessor.GetCurrentEpoch(state);

            if (data.Target.Epoch != previousEpoch && data.Target.Epoch != currentEpoch)
            {
                throw new ArgumentOutOfRangeException("attestation.Data.Target.Epoch", data.Target.Epoch, $"Attestation data target epoch must be either the previous epoch {previousEpoch} or the current epoch {currentEpoch}.");
            }
            var minimumSlot = data.Slot + timeParameters.MinimumAttestationInclusionDelay;
            var maximumSlot = data.Slot + timeParameters.SlotsPerEpoch;

            if (state.Slot < minimumSlot)
            {
                throw new Exception($"Current state slot {state.Slot} must be equal or greater than the attestion slot {data.Slot} plus minimum delay {timeParameters.MinimumAttestationInclusionDelay}.");
            }
            if (state.Slot > maximumSlot)
            {
                throw new Exception($"Current state slot {state.Slot} must be equal or less than the attestation slot {data.Slot} plus slots per epoch {timeParameters.SlotsPerEpoch}.");
            }

            var committee = _beaconStateAccessor.GetBeaconCommittee(state, data.Slot, data.Index);

            if (attestation.AggregationBits.Count != attestation.CustodyBits.Count)
            {
                throw new Exception($"The attestation aggregation bit length {attestation.AggregationBits.Count} must be the same as the custody bit length {attestation.CustodyBits.Count}.");
            }
            if (attestation.AggregationBits.Count != committee.Count)
            {
                throw new Exception($"The attestation aggregation bit (and custody bit) length {attestation.AggregationBits.Count} must be the same as the committee length {committee.Count}.");
            }

            var inclusionDelay     = state.Slot - data.Slot;
            var proposerIndex      = _beaconStateAccessor.GetBeaconProposerIndex(state);
            var pendingAttestation = new PendingAttestation(attestation.AggregationBits, data, inclusionDelay, proposerIndex);

            if (data.Target.Epoch == currentEpoch)
            {
                if (!data.Source.Equals(state.CurrentJustifiedCheckpoint))
                {
                    throw new Exception($"For a current epoch target attestation the data source checkpoint {data.Source} must be the same as the current justified checkpoint {state.CurrentJustifiedCheckpoint}.");
                }
                state.AddCurrentAttestation(pendingAttestation);
            }
            else
            {
                if (!data.Source.Equals(state.PreviousJustifiedCheckpoint))
                {
                    throw new Exception($"For a previous epoch target attestation the data source checkpoint {data.Source} must be the same as the previous justified checkpoint {state.PreviousJustifiedCheckpoint}.");
                }
                state.AddPreviousAttestation(pendingAttestation);
            }

            // Check signature
            var indexedAttestation = _beaconStateAccessor.GetIndexedAttestation(state, attestation);
            var domain             = _beaconStateAccessor.GetDomain(state, _signatureDomainOptions.CurrentValue.BeaconAttester, data.Target.Epoch);
            var isValid            = _beaconChainUtility.IsValidIndexedAttestation(state, indexedAttestation, domain);

            if (!isValid)
            {
                throw new Exception($"Indexed attestation {indexedAttestation} is not valid.");
            }
        }