/// <summary>
        /// Slash the validator with index ``slashed_index``.
        /// </summary>
        public void SlashValidator(BeaconState state, ValidatorIndex slashedIndex, ValidatorIndex?optionalWhistleblowerIndex)
        {
            RewardsAndPenalties rewardsAndPenalties = _rewardsAndPenaltiesOptions.CurrentValue;
            StateListLengths    stateListLengths    = _stateListLengthOptions.CurrentValue;

            Epoch epoch = _beaconStateAccessor.GetCurrentEpoch(state);

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

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

            validator.SetWithdrawableEpoch(withdrawableEpoch);

            Epoch slashingsIndex = (Epoch)(epoch % stateListLengths.EpochsPerSlashingsVector);

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

            DecreaseBalance(state, slashedIndex, slashingPenalty);

            // Apply proposer and whistleblower rewards
            ValidatorIndex proposerIndex      = _beaconStateAccessor.GetBeaconProposerIndex(state);
            ValidatorIndex whistleblowerIndex = optionalWhistleblowerIndex ?? proposerIndex;

            Gwei whistleblowerReward = validator.EffectiveBalance / rewardsAndPenalties.WhistleblowerRewardQuotient;
            Gwei proposerReward      = whistleblowerReward / rewardsAndPenalties.ProposerRewardQuotient;

            IncreaseBalance(state, proposerIndex, proposerReward);
            IncreaseBalance(state, whistleblowerIndex, whistleblowerReward - proposerReward);
        }
Example #2
0
        public void ProcessFinalUpdates(BeaconState state)
        {
            _logger.LogInformation(Event.ProcessFinalUpdates, "Process epoch final updates state {BeaconState}", state);

            var timeParameters   = _timeParameterOptions.CurrentValue;
            var gweiValues       = _gweiValueOptions.CurrentValue;
            var stateListLengths = _stateListLengthOptions.CurrentValue;

            var currentEpoch = _beaconStateAccessor.GetCurrentEpoch(state);
            var nextEpoch    = currentEpoch + new Epoch(1);

            // Reset eth1 data votes
            var nextSlot = state.Slot + new Slot(1);

            if (nextSlot % timeParameters.SlotsPerEth1VotingPeriod == Slot.Zero)
            {
                state.ClearEth1DataVotes();
            }

            // Update effective balances with hysteresis
            var halfIncrement = gweiValues.EffectiveBalanceIncrement / 2;

            for (var index = 0; index < state.Validators.Count; index++)
            {
                var validator = state.Validators[index];
                var balance   = state.Balances[index];
                if (balance < validator.EffectiveBalance || (validator.EffectiveBalance + (halfIncrement * 3)) < balance)
                {
                    var roundedBalance   = balance - (balance % gweiValues.EffectiveBalanceIncrement);
                    var effectiveBalance = Gwei.Min(roundedBalance, gweiValues.MaximumEffectiveBalance);
                    validator.SetEffectiveBalance(effectiveBalance);
                }
            }

            // Reset slashings
            var slashingsIndex = nextEpoch % stateListLengths.EpochsPerSlashingsVector;

            state.SetSlashings(slashingsIndex, Gwei.Zero);

            // Set randao mix
            var randaoIndex = nextEpoch % stateListLengths.EpochsPerHistoricalVector;
            var randaoMix   = _beaconStateAccessor.GetRandaoMix(state, currentEpoch);

            state.SetRandaoMix(randaoIndex, randaoMix);

            // Set historical root accumulator
            var divisor = timeParameters.SlotsPerHistoricalRoot / timeParameters.SlotsPerEpoch;

            if ((ulong)nextEpoch % divisor == 0)
            {
                var historicalBatch = new HistoricalBatch(state.BlockRoots.ToArray(), state.StateRoots.ToArray());
                var historicalRoot  = historicalBatch.HashTreeRoot();
                state.AddHistoricalRoot(historicalRoot);
            }

            // Rotate current/previous epoch attestations
            state.SetPreviousEpochAttestations(state.CurrentEpochAttestations);
            state.SetCurrentEpochAttestations(new PendingAttestation[0]);
        }
Example #3
0
        private void SlashValidators(IServiceProvider testServiceProvider, BeaconState state, IEnumerable <int> indices, IEnumerable <Epoch> outEpochs)
        {
            StateListLengths stateListLengths = testServiceProvider.GetService <IOptions <StateListLengths> >().Value;

            BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>();
            BeaconStateMutator  beaconStateMutator  = testServiceProvider.GetService <BeaconStateMutator>();

            Gwei totalSlashedBalance = Gwei.Zero;
            var  items = indices.Zip(outEpochs, (index, outEpoch) => new { index, outEpoch });

            foreach (var item in items)
            {
                Validator validator = state.Validators[item.index];
                validator.SetSlashed();
                beaconStateMutator.InitiateValidatorExit(state, new ValidatorIndex((ulong)item.index));
                validator.SetWithdrawableEpoch(item.outEpoch);
                totalSlashedBalance += validator.EffectiveBalance;
            }

            Epoch currentEpoch   = beaconStateAccessor.GetCurrentEpoch(state);
            Epoch slashingsIndex = (Epoch)(currentEpoch % stateListLengths.EpochsPerSlashingsVector);

            state.SetSlashings(slashingsIndex, totalSlashedBalance);
        }
Example #4
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);
        }