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]); }
public void ProcessRandao(BeaconState state, BeaconBlockBody body) { _logger.LogInformation(Event.ProcessRandao, "Process block randao for block body {BeaconBlockBody}", body); var epoch = _beaconStateAccessor.GetCurrentEpoch(state); // Verify RANDAO reveal var beaconProposerIndex = _beaconStateAccessor.GetBeaconProposerIndex(state); var proposer = state.Validators[(int)(ulong)beaconProposerIndex]; var epochRoot = epoch.HashTreeRoot(); var domain = _beaconStateAccessor.GetDomain(state, _signatureDomainOptions.CurrentValue.Randao, Epoch.None); var validRandaoReveal = _cryptographyService.BlsVerify(proposer.PublicKey, epochRoot, body.RandaoReveal, domain); if (!validRandaoReveal) { throw new Exception($"Randao reveal {body.RandaoReveal} must match proposer public key {proposer.PublicKey}"); } // Mix in RANDAO reveal var randaoMix = _beaconStateAccessor.GetRandaoMix(state, epoch); var randaoHash = _cryptographyService.Hash(body.RandaoReveal.AsSpan()); var mix = randaoMix.Xor(randaoHash); var randaoIndex = epoch % _stateListLengthOptions.CurrentValue.EpochsPerHistoricalVector; state.SetRandaoMix(randaoIndex, mix); }