// Run ``process_deposit``, yielding: // - pre-state('pre') // - deposit('deposit') // - post-state('post'). //If ``valid == False``, run expecting ``AssertionError`` private void RunDepositProcessing(IServiceProvider testServiceProvider, BeaconState state, Deposit deposit, ValidatorIndex validatorIndex, bool expectValid, bool effective) { GweiValues gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); int preValidatorCount = state.Validators.Count; Gwei preBalance = Gwei.Zero; if ((int)(ulong)validatorIndex < preValidatorCount) { preBalance = TestState.GetBalance(state, validatorIndex); } if (!expectValid) { Should.Throw <Exception>(() => { beaconStateTransition.ProcessDeposit(state, deposit); }); return; } beaconStateTransition.ProcessDeposit(state, deposit); if (!effective) { state.Validators.Count.ShouldBe(preValidatorCount); state.Balances.Count.ShouldBe(preValidatorCount); if ((int)(ulong)validatorIndex < preValidatorCount) { Gwei balance = TestState.GetBalance(state, validatorIndex); balance.ShouldBe(preBalance); } } else { if ((int)(ulong)validatorIndex < preValidatorCount) { // top up state.Validators.Count.ShouldBe(preValidatorCount); state.Balances.Count.ShouldBe(preValidatorCount); } else { // new validator state.Validators.Count.ShouldBe(preValidatorCount + 1); state.Balances.Count.ShouldBe(preValidatorCount + 1); } Gwei balance = TestState.GetBalance(state, validatorIndex); Gwei expectedBalance = preBalance + deposit.Data.Item.Amount; balance.ShouldBe(expectedBalance); Gwei expectedEffectiveBalance = Gwei.Min(gweiValues.MaximumEffectiveBalance, expectedBalance); expectedEffectiveBalance -= expectedEffectiveBalance % gweiValues.EffectiveBalanceIncrement; state.Validators[(int)(ulong)validatorIndex].EffectiveBalance.ShouldBe(expectedEffectiveBalance); } state.Eth1DepositIndex.ShouldBe(state.Eth1Data.DepositCount); }
// Run ``process_attester_slashing``, yielding: // - pre-state('pre') // - attester_slashing('attester_slashing') // - post-state('post'). //If ``valid == False``, run expecting ``AssertionError`` private void RunAttesterSlashingProcessing(IServiceProvider testServiceProvider, BeaconState state, AttesterSlashing attesterSlashing, bool expectValid) { ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); StateListLengths stateListLengths = testServiceProvider.GetService <IOptions <StateListLengths> >().Value; RewardsAndPenalties rewardsAndPenalties = testServiceProvider.GetService <IOptions <RewardsAndPenalties> >().Value; BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); if (!expectValid) { Should.Throw <Exception>(() => { beaconStateTransition.ProcessAttesterSlashing(state, attesterSlashing); }); return; } var slashedIndices = attesterSlashing.Attestation1.CustodyBit0Indices .Union(attesterSlashing.Attestation1.CustodyBit1Indices) .ToList(); ValidatorIndex proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(state); Gwei preProposerBalance = TestState.GetBalance(state, proposerIndex); var preSlashings = slashedIndices.ToDictionary(x => x, x => TestState.GetBalance(state, x)); var preWithdrawableEpochs = slashedIndices.ToDictionary(x => x, x => state.Validators[(int)(ulong)x].WithdrawableEpoch); Gwei totalProposerRewards = preSlashings.Values.Aggregate(Gwei.Zero, (sum, x) => sum + x / rewardsAndPenalties.WhistleblowerRewardQuotient); // Process slashing beaconStateTransition.ProcessAttesterSlashing(state, attesterSlashing); foreach (ValidatorIndex slashedIndex in slashedIndices) { Console.WriteLine($"Checking index {slashedIndex}"); Epoch preWithdrawableEpoch = preWithdrawableEpochs[slashedIndex]; Validator slashedValidator = state.Validators[(int)(ulong)slashedIndex]; // Check Slashing slashedValidator.IsSlashed.ShouldBeTrue(); slashedValidator.ExitEpoch.ShouldBeLessThan(chainConstants.FarFutureEpoch); if (preWithdrawableEpoch < chainConstants.FarFutureEpoch) { ulong slashingsEpoch = beaconStateAccessor.GetCurrentEpoch(state) + stateListLengths.EpochsPerSlashingsVector; Epoch expectedWithdrawableEpoch = Epoch.Max(preWithdrawableEpoch, (Epoch)slashingsEpoch); slashedValidator.WithdrawableEpoch.ShouldBe(expectedWithdrawableEpoch); } else { slashedValidator.WithdrawableEpoch.ShouldBeLessThan(chainConstants.FarFutureEpoch); } Gwei preSlashing = preSlashings[slashedIndex]; Gwei slashedBalance = TestState.GetBalance(state, slashedIndex); slashedBalance.ShouldBeLessThan(preSlashing); } if (!slashedIndices.Contains(proposerIndex)) { // gained whistleblower reward Gwei expectedProposerBalance = preProposerBalance + totalProposerRewards; Gwei proposerBalance = TestState.GetBalance(state, proposerIndex); proposerBalance.ShouldBe(expectedProposerBalance); } else { // gained rewards for all slashings, which may include others. And only lost that of themselves. Gwei expectedProposerBalance = preProposerBalance + totalProposerRewards - (preSlashings[proposerIndex] / rewardsAndPenalties.MinimumSlashingPenaltyQuotient); Gwei proposerBalance = TestState.GetBalance(state, proposerIndex); proposerBalance.ShouldBe(expectedProposerBalance); } }