/// <summary> /// Processes to the next epoch transition, up to and including the sub-transition named ``process_name`` /// - pre-state('pre'), state before calling ``process_name`` /// - post-state('post'), state after calling ``process_name`` /// </summary> public static void RunEpochProcessingWith(IServiceProvider testServiceProvider, BeaconState state, TestProcessStep step) { RunEpochProcessingTo(testServiceProvider, state, step); BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); if (step == TestProcessStep.ProcessJustificationAndFinalization) { beaconStateTransition.ProcessJustificationAndFinalization(state); return; } if (step == TestProcessStep.ProcessRewardsAndPenalties) { beaconStateTransition.ProcessRewardsAndPenalties(state); return; } if (step == TestProcessStep.ProcessRegistryUpdates) { beaconStateTransition.ProcessRegistryUpdates(state); return; } if (step == TestProcessStep.ProcessSlashings) { beaconStateTransition.ProcessSlashings(state); return; } if (step == TestProcessStep.ProcessFinalUpdates) { beaconStateTransition.ProcessFinalUpdates(state); return; } throw new NotImplementedException(); }
/// <summary> /// Processes to the next epoch transition, up to, but not including, the sub-transition named ``process_name`` /// </summary> public static void RunEpochProcessingTo(IServiceProvider testServiceProvider, BeaconState state, TestProcessStep step) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); Slot slot = (Slot)(state.Slot + (timeParameters.SlotsPerEpoch - state.Slot % timeParameters.SlotsPerEpoch) - 1UL); // transition state to slot before epoch state transition beaconStateTransition.ProcessSlots(state, slot); // start transitioning, do one slot update before the epoch itself. beaconStateTransition.ProcessSlot(state); // process components of epoch transition before final-updates if (step == TestProcessStep.ProcessJustificationAndFinalization) { return; } // Note: only run when present. Later phases introduce more to the epoch-processing. beaconStateTransition.ProcessJustificationAndFinalization(state); if (step == TestProcessStep.ProcessRewardsAndPenalties) { return; } beaconStateTransition.ProcessRewardsAndPenalties(state); if (step == TestProcessStep.ProcessRegistryUpdates) { return; } beaconStateTransition.ProcessRegistryUpdates(state); if (step == TestProcessStep.ProcessSlashings) { return; } beaconStateTransition.ProcessSlashings(state); if (step == TestProcessStep.ProcessFinalUpdates) { return; } beaconStateTransition.ProcessFinalUpdates(state); }
public void EffectiveBalanceHysteresis() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); //# Prepare state up to the final-updates. //# Then overwrite the balances, we only want to focus to be on the hysteresis based changes. TestProcessUtility.RunEpochProcessingTo(testServiceProvider, state, TestProcessStep.ProcessFinalUpdates); GweiValues gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); // Set some edge cases for balances Gwei maximum = gweiValues.MaximumEffectiveBalance; Gwei minimum = gweiValues.EjectionBalance; Gwei increment = gweiValues.EffectiveBalanceIncrement; Gwei halfIncrement = increment / 2; EffectiveBalanceCase[] testCases = new[] { new EffectiveBalanceCase(maximum, maximum, maximum, "as-is"), new EffectiveBalanceCase(maximum, (Gwei)(maximum - 1), maximum - increment, "round down, step lower"), new EffectiveBalanceCase(maximum, (Gwei)(maximum + 1), maximum, "round down"), new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment), maximum - increment, "exactly 1 step lower"), new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment - 1), maximum - (increment * 2), "just 1 over 1 step lower"), new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment + 1), maximum - increment, "close to 1 step lower"), new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 3)), minimum, "bigger balance, but not high enough"), new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 3) + 1), minimum + increment, "bigger balance, high enough, but small step"), new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4) - 1), minimum + increment, "bigger balance, high enough, close to double step"), new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4)), minimum + (increment * 2), "exact two step balance increment"), new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4) + 1), minimum + (increment * 2), "over two steps, round down"), }; Epoch currentEpoch = beaconStateAccessor.GetCurrentEpoch(state); for (int index = 0; index < testCases.Length; index++) { Validator validator = state.Validators[index]; bool isActive = beaconChainUtility.IsActiveValidator(validator, currentEpoch); isActive.ShouldBeTrue(); EffectiveBalanceCase testCase = testCases[index]; validator.SetEffectiveBalance(testCase.PreEffective); ValidatorIndex validatorIndex = new ValidatorIndex((ulong)index); state.SetBalance(validatorIndex, testCase.Balance); } // Act beaconStateTransition.ProcessFinalUpdates(state); // Assert for (int index = 0; index < testCases.Length; index++) { EffectiveBalanceCase testCase = testCases[index]; Validator validator = state.Validators[index]; validator.EffectiveBalance.ShouldBe(testCase.PostEffective, testCase.Name); } }