public void InvalidSignature() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); // move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit ulong move = timeParameters.SlotsPerEpoch * (ulong)timeParameters.PersistentCommitteePeriod; ulong newSlot = state.Slot + move; state.SetSlot((Slot)newSlot); Epoch currentEpoch = beaconStateAccessor.GetCurrentEpoch(state); ValidatorIndex validatorIndex = beaconStateAccessor.GetActiveValidatorIndices(state, currentEpoch)[0]; Validator validator = state.Validators[(int)(ulong)validatorIndex]; var privateKey = TestKeys.PublicKeyToPrivateKey(validator.PublicKey, timeParameters); VoluntaryExit voluntaryExit = TestVoluntaryExit.BuildVoluntaryExit(testServiceProvider, state, currentEpoch, validatorIndex, privateKey, signed: false); RunVoluntaryExitProcessing(testServiceProvider, state, voluntaryExit, expectValid: false); }
public void BasicGetCommitteeAssignment(ulong index, ulong slot, ulong committeeIndex) { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); // Act ValidatorAssignments validatorAssignments = testServiceProvider.GetService <ValidatorAssignments>(); ValidatorIndex validatorIndex = new ValidatorIndex(index); CommitteeAssignment committeeAssignment = validatorAssignments.GetCommitteeAssignment(state, Epoch.Zero, validatorIndex); // Assert Console.WriteLine("Validator [{0}] {1} in slot {2} committee {3}", validatorIndex, state.Validators[(int)validatorIndex].PublicKey, committeeAssignment.Slot, committeeAssignment.CommitteeIndex); Slot expectedSlot = new Slot(slot); CommitteeIndex expectedCommitteeIndex = new CommitteeIndex(committeeIndex); committeeAssignment.Slot.ShouldBe(expectedSlot); committeeAssignment.CommitteeIndex.ShouldBe(expectedCommitteeIndex); }
/// <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); }
/// <summary> /// Return from ``indices`` a random index sampled by effective balance. /// </summary> public ValidatorIndex ComputeProposerIndex(BeaconState state, IList <ValidatorIndex> indices, Hash32 seed) { if (!indices.Any()) { throw new ArgumentException("Indices can not be empty", nameof(indices)); } const ulong maxRandomByte = (1 << 8) - 1; var indexCount = (ulong)indices.Count(); var index = (ulong)0; while (true) { var initialValidatorIndex = new ValidatorIndex(index % indexCount); var shuffledIndex = ComputeShuffledIndex(initialValidatorIndex, indexCount, seed); var candidateIndex = indices[(int)(ulong)shuffledIndex]; var randomInputBytes = new Span <byte>(new byte[40]); seed.AsSpan().CopyTo(randomInputBytes); BitConverter.TryWriteBytes(randomInputBytes.Slice(32), index / 32); if (!BitConverter.IsLittleEndian) { randomInputBytes.Slice(32).Reverse(); } var randomHash = _cryptographyService.Hash(randomInputBytes); var random = randomHash.AsSpan()[(int)(index % 32)]; var effectiveBalance = state.Validators[(int)(ulong)candidateIndex].EffectiveBalance; if ((effectiveBalance * maxRandomByte) >= (_gweiValueOptions.CurrentValue.MaximumEffectiveBalance * random)) { return(candidateIndex); } index++; } }
public DutyDetails(BlsPublicKey validatorPublicKey, ValidatorIndex validatorIndex) { ValidatorPublicKey = validatorPublicKey; ValidatorIndex = validatorIndex; }
// 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); } }
public static void Ize(out UInt256 root, ValidatorIndex container) { Ize(out root, container.Number); }
public VoluntaryExit(Epoch epoch, ValidatorIndex validatorIndex, BlsSignature signature) { Epoch = epoch; ValidatorIndex = validatorIndex; Signature = signature; }
private async Task <Duty> CheckHistoricalSlotsAsync(IStore store, IReadOnlyList <Root> historicalBlockRoots, Slot fromSlot, Slot startSlot, ValidatorIndex validatorIndex, Duty duty) { TimeParameters timeParameters = _timeParameterOptions.CurrentValue; Slot previousSlot = fromSlot; while (true) { previousSlot -= Slot.One; int index = (int)(previousSlot % timeParameters.SlotsPerHistoricalRoot); Root previousRoot = historicalBlockRoots[index]; BeaconState previousState = await store.GetBlockStateAsync(previousRoot).ConfigureAwait(false); duty = CheckStateDuty(previousState, validatorIndex, duty); if (previousSlot <= startSlot || (duty.AttestationSlot != Slot.None && duty.BlockProposalSlot != Slot.None)) { break; } } return(duty); }
public static VoluntaryExit BuildVoluntaryExit(IServiceProvider testServiceProvider, Epoch epoch, ValidatorIndex validatorIndex) { var voluntaryExit = new VoluntaryExit(epoch, validatorIndex); return(voluntaryExit); }
private static void Encode(Span <byte> span, ValidatorIndex value, ref int offset) { BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(offset), value.Number); offset += Ssz.ValidatorIndexLength; }
public static void SignBlock(IServiceProvider testServiceProvider, BeaconState state, BeaconBlock block, ValidatorIndex proposerIndex) { var miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; var timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; var maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; var signatureDomains = testServiceProvider.GetService <IOptions <SignatureDomains> >().Value; var beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); var beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); var beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); if (state.Slot > block.Slot) { throw new ArgumentOutOfRangeException("block.Slot", block.Slot, $"Slot of block must be equal or less that state slot {state.Slot}"); } var blockEpoch = beaconChainUtility.ComputeEpochAtSlot(block.Slot); if (proposerIndex == ValidatorIndex.None) { if (block.Slot == state.Slot) { proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(state); } else { var stateEpoch = beaconChainUtility.ComputeEpochAtSlot(state.Slot); if (stateEpoch + 1 > blockEpoch) { Console.WriteLine("WARNING: Block slot far away, and no proposer index manually given." + " Signing block is slow due to transition for proposer index calculation."); } // use stub state to get proposer index of future slot var stubState = BeaconState.Clone(state); beaconStateTransition.ProcessSlots(stubState, block.Slot); proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(stubState); } } var privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); var privateKey = privateKeys[(int)(ulong)proposerIndex]; var randaoDomain = beaconStateAccessor.GetDomain(state, signatureDomains.Randao, blockEpoch); var randaoRevealHash = blockEpoch.HashTreeRoot(); var randaoReveal = TestSecurity.BlsSign(randaoRevealHash, privateKey, randaoDomain); block.Body.SetRandaoReveal(randaoReveal); var signatureDomain = beaconStateAccessor.GetDomain(state, signatureDomains.BeaconProposer, blockEpoch); var signingRoot = block.SigningRoot(miscellaneousParameters, maxOperationsPerBlock); var signature = TestSecurity.BlsSign(signingRoot, privateKey, signatureDomain); block.SetSignature(signature); }
public bool TryGetLatestMessage(ValidatorIndex validatorIndex, out LatestMessage latestMessage) => _latestMessages.TryGetValue(validatorIndex, out latestMessage);
public void SetLatestMessage(ValidatorIndex validatorIndex, LatestMessage latestMessage) => _latestMessages[validatorIndex] = latestMessage;
/// <summary> /// Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount. /// </summary> public static Deposit PrepareStateAndDeposit(IServiceProvider testServiceProvider, BeaconState state, ValidatorIndex validatorIndex, Gwei amount, Bytes32 withdrawalCredentials, bool signed) { ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); InitialValues initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; IBeaconChainUtility beaconChainUtility = testServiceProvider.GetService <IBeaconChainUtility>(); BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); IDepositStore depositStore = testServiceProvider.GetService <IDepositStore>(); byte[][] privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); BlsPublicKey[] publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); byte[] privateKey = privateKeys[(int)(ulong)validatorIndex]; BlsPublicKey publicKey = publicKeys[(int)(ulong)validatorIndex]; if (withdrawalCredentials == Bytes32.Zero) { // insecurely use pubkey as withdrawal key if no credentials provided byte[] withdrawalCredentialBytes = TestSecurity.Hash(publicKey.AsSpan()); withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix; withdrawalCredentials = new Bytes32(withdrawalCredentialBytes); } DepositData depositData = BuildDeposit(testServiceProvider, state, publicKey, privateKey, amount, withdrawalCredentials, signed); Deposit deposit = depositStore.Place(depositData); state.SetEth1DepositIndex(0); state.Eth1Data.SetDepositRoot(depositStore.DepositData.Root); state.Eth1Data.SetDepositCount((ulong)depositStore.Deposits.Count); return(deposit); }
public void EffectiveBalanceHysteresis() { // Arrange var testServiceProvider = TestSystem.BuildTestServiceProvider(); var 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); var gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; var beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); var beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); var beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); // Set some edge cases for balances var maximum = gweiValues.MaximumEffectiveBalance; var minimum = gweiValues.EjectionBalance; var increment = gweiValues.EffectiveBalanceIncrement; var halfIncrement = increment / 2; var 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"), }; var currentEpoch = beaconStateAccessor.GetCurrentEpoch(state); for (var index = 0; index < testCases.Length; index++) { var validator = state.Validators[index]; var isActive = beaconChainUtility.IsActiveValidator(validator, currentEpoch); isActive.ShouldBeTrue(); var testCase = testCases[index]; validator.SetEffectiveBalance(testCase.PreEffective); var validatorIndex = new ValidatorIndex((ulong)index); state.SetBalance(validatorIndex, testCase.Balance); } // Act beaconStateTransition.ProcessFinalUpdates(state); // Assert for (var index = 0; index < testCases.Length; index++) { var testCase = testCases[index]; var validator = state.Validators[index]; validator.EffectiveBalance.ShouldBe(testCase.PostEffective, testCase.Name); } }
/// <summary> /// Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount. /// </summary> public static Deposit PrepareStateAndDeposit(IServiceProvider testServiceProvider, BeaconState state, ValidatorIndex validatorIndex, Gwei amount, Hash32 withdrawalCredentials, bool signed) { var chainConstants = testServiceProvider.GetService <ChainConstants>(); var initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; var timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; var beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); var beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); var privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); var publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); var privateKey = privateKeys[(int)(ulong)validatorIndex]; var publicKey = publicKeys[(int)(ulong)validatorIndex]; if (withdrawalCredentials == Hash32.Zero) { // insecurely use pubkey as withdrawal key if no credentials provided var withdrawalCredentialBytes = TestSecurity.Hash(publicKey.AsSpan()); withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix; withdrawalCredentials = new Hash32(withdrawalCredentialBytes); } var depositDataList = new List <DepositData>(); (var deposit, var depositRoot) = BuildDeposit(testServiceProvider, state, depositDataList, publicKey, privateKey, amount, withdrawalCredentials, signed); state.SetEth1DepositIndex(0); state.Eth1Data.SetDepositRoot(depositRoot); state.Eth1Data.SetDepositCount((ulong)depositDataList.Count); return(deposit); }
public static void Encode(Span <byte> span, ValidatorIndex value) { Encode(span, value.Number); }
public async Task <ValidatorDuty> GetValidatorDutyAsync(BlsPublicKey validatorPublicKey, Epoch epoch) { Root head = await _forkChoice.GetHeadAsync(_store).ConfigureAwait(false); BeaconState headState = await _store.GetBlockStateAsync(head).ConfigureAwait(false); Epoch currentEpoch = _beaconStateAccessor.GetCurrentEpoch(headState); Epoch nextEpoch = currentEpoch + Epoch.One; if (epoch == Epoch.None) { epoch = currentEpoch; } else if (epoch > nextEpoch) { throw new ArgumentOutOfRangeException(nameof(epoch), epoch, $"Duties cannot look ahead more than the next epoch {nextEpoch}."); } TimeParameters timeParameters = _timeParameterOptions.CurrentValue; Slot startSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(epoch); Slot endSlot = startSlot + new Slot(timeParameters.SlotsPerEpoch); Duty duty = new Duty() { AttestationSlot = Slot.None, AttestationCommitteeIndex = CommitteeIndex.None, BlockProposalSlot = Slot.None }; if (epoch == nextEpoch) { // Clone for next or current, so that it can be safely mutated (transitioned forward) BeaconState state = BeaconState.Clone(headState); _beaconStateTransition.ProcessSlots(state, startSlot); // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); duty = CheckStateDuty(state, validatorIndex, duty); // Check future states duty = CheckFutureSlots(state, endSlot, validatorIndex, duty); } else if (epoch == currentEpoch) { // Take block slot and roots before cloning (for historical checks) IReadOnlyList <Root> historicalBlockRoots = headState.BlockRoots; Slot fromSlot = headState.Slot; BeaconState state = BeaconState.Clone(headState); // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); duty = CheckStateDuty(state, validatorIndex, duty); // Check future states duty = CheckFutureSlots(state, endSlot, validatorIndex, duty); // Check historical states if (startSlot < fromSlot && (duty.AttestationSlot == Slot.None || duty.BlockProposalSlot == Slot.None)) { duty = await CheckHistoricalSlotsAsync(_store, historicalBlockRoots, fromSlot, startSlot, validatorIndex, duty).ConfigureAwait(false); } } else { Root endRoot = await _forkChoice.GetAncestorAsync(_store, head, endSlot - Slot.One); BeaconState state = await _store.GetBlockStateAsync(endRoot).ConfigureAwait(false); // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); duty = CheckStateDuty(state, validatorIndex, duty); // Check historical states IReadOnlyList <Root> historicalBlockRoots = state.BlockRoots; if (duty.AttestationSlot == Slot.None || duty.BlockProposalSlot == Slot.None) { Slot fromSlot = state.Slot; duty = await CheckHistoricalSlotsAsync(_store, historicalBlockRoots, fromSlot, startSlot, validatorIndex, duty).ConfigureAwait(false); } } // HACK: Shards were removed from Phase 0, but analogy is committee index, so use for initial testing. Shard attestationShard = new Shard((ulong)duty.AttestationCommitteeIndex); ValidatorDuty validatorDuty = new ValidatorDuty(validatorPublicKey, duty.AttestationSlot, attestationShard, duty.BlockProposalSlot); return(validatorDuty); }
public void SetBalance(ValidatorIndex validatorIndex, Gwei balance) => _balances[(int)validatorIndex] = balance;
public static Gwei GetBalance(BeaconState state, ValidatorIndex proposerIndex) { return(state.Balances[(int)(ulong)proposerIndex]); }
public static VoluntaryExit BuildVoluntaryExit(IServiceProvider testServiceProvider, BeaconState state, Epoch epoch, ValidatorIndex validatorIndex, byte[] privateKey, bool signed) { var voluntaryExit = new VoluntaryExit(epoch, validatorIndex, BlsSignature.Empty); if (signed) { SignVoluntaryExit(testServiceProvider, state, voluntaryExit, privateKey); } return(voluntaryExit); }
public static SszElement ToSszBasicElement(this ValidatorIndex item) { return(new SszBasicElement((ulong)item)); }
public static SignedBeaconBlock SignBlock(IServiceProvider testServiceProvider, BeaconState state, BeaconBlock block, ValidatorIndex proposerIndex) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; SignatureDomains signatureDomains = testServiceProvider.GetService <IOptions <SignatureDomains> >().Value; ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); if (state.Slot > block.Slot) { throw new ArgumentOutOfRangeException("block.Slot", block.Slot, $"Slot of block must be equal or less that state slot {state.Slot}"); } Epoch blockEpoch = beaconChainUtility.ComputeEpochAtSlot(block.Slot); if (proposerIndex == ValidatorIndex.None) { if (block.Slot == state.Slot) { proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(state); } else { Epoch stateEpoch = beaconChainUtility.ComputeEpochAtSlot(state.Slot); if (stateEpoch + 1 > blockEpoch) { Console.WriteLine("WARNING: Block slot far away, and no proposer index manually given." + " Signing block is slow due to transition for proposer index calculation."); } // use stub state to get proposer index of future slot BeaconState stubState = BeaconState.Clone(state); beaconStateTransition.ProcessSlots(stubState, block.Slot); proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(stubState); } } byte[][] privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); byte[] privateKey = privateKeys[(int)(ulong)proposerIndex]; Root blockHashTreeRoot = cryptographyService.HashTreeRoot(block); Domain proposerDomain = beaconStateAccessor.GetDomain(state, signatureDomains.BeaconProposer, blockEpoch); Root signingRoot = beaconChainUtility.ComputeSigningRoot(blockHashTreeRoot, proposerDomain); BlsSignature signature = TestSecurity.BlsSign(signingRoot, privateKey); return(new SignedBeaconBlock(block, signature)); }
public Task SetLatestMessageAsync(ValidatorIndex validatorIndex, LatestMessage latestMessage) { _latestMessages[validatorIndex] = latestMessage; return(Task.CompletedTask); }
// 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); }
public bool IsProposer(BeaconState state, ValidatorIndex validatorIndex) { ValidatorIndex stateProposerIndex = _beaconStateAccessor.GetBeaconProposerIndex(state); return(stateProposerIndex.Equals(validatorIndex)); }
public async Task <ValidatorDuty> GetValidatorDutyAsync(BlsPublicKey validatorPublicKey, Epoch epoch) { if (!_storeProvider.TryGetStore(out IStore? retrievedStore)) { throw new Exception("Beacon chain is currently syncing or waiting for genesis."); } IStore store = retrievedStore !; Hash32 head = await _forkChoice.GetHeadAsync(store); if (!store.TryGetBlockState(head, out BeaconState? headState)) { throw new Exception($"Head state {head} not found."); } Epoch currentEpoch = _beaconStateAccessor.GetCurrentEpoch(headState !); Epoch nextEpoch = currentEpoch + Epoch.One; if (epoch == Epoch.None) { epoch = currentEpoch; } else if (epoch > nextEpoch) { throw new ArgumentOutOfRangeException(nameof(epoch), epoch, $"Duties cannot look ahead more than the next epoch {nextEpoch}."); } TimeParameters timeParameters = _timeParameterOptions.CurrentValue; Slot startSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(epoch); Slot endSlot = startSlot + new Slot(timeParameters.SlotsPerEpoch); Slot attestationSlot = Slot.None; CommitteeIndex attestationCommitteeIndex = CommitteeIndex.None; Slot blockProposalSlot = Slot.None; if (epoch == nextEpoch) { // Clone for next or current, so that it can be safely mutated (transitioned forward) BeaconState state = BeaconState.Clone(headState !); _beaconStateTransition.ProcessSlots(state, startSlot); // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); CheckStateDuty(state, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); // Check future states CheckFutureSlots(state, endSlot, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); } else if (epoch == currentEpoch) { // Take block slot and roots before cloning (for historical checks) IReadOnlyList <Hash32> historicalBlockRoots = headState !.BlockRoots; Slot fromSlot = headState !.Slot; BeaconState state = BeaconState.Clone(headState !); // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); CheckStateDuty(state, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); // Check future states CheckFutureSlots(state, endSlot, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); // Check historical states if (startSlot < fromSlot && (attestationSlot == Slot.None || blockProposalSlot == Slot.None)) { CheckHistoricalSlots(store, historicalBlockRoots, fromSlot, startSlot, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); } } else { Hash32 endRoot = _forkChoice.GetAncestor(store, head, endSlot - Slot.One); if (!store.TryGetBlockState(endRoot, out BeaconState? endState)) { throw new Exception($"State {endRoot} for slot {endSlot} not found."); } BeaconState state = endState !; // Check base state ValidatorIndex validatorIndex = CheckValidatorIndex(state, validatorPublicKey); CheckStateDuty(state, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); // Check historical states IReadOnlyList <Hash32> historicalBlockRoots = state.BlockRoots; Slot fromSlot = state.Slot; if (attestationSlot == Slot.None || blockProposalSlot == Slot.None) { CheckHistoricalSlots(store, historicalBlockRoots, fromSlot, startSlot, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); } } // HACK: Shards were removed from Phase 0, but analogy is committee index, so use for initial testing. Shard attestationShard = new Shard((ulong)attestationCommitteeIndex); ValidatorDuty validatorDuty = new ValidatorDuty(validatorPublicKey, attestationSlot, attestationShard, blockProposalSlot); return(validatorDuty); }
/// <summary> /// Return the committee assignment in the ``epoch`` for ``validator_index``. /// ``assignment`` returned is a tuple of the following form: /// * ``assignment[0]`` is the list of validators in the committee /// * ``assignment[1]`` is the index to which the committee is assigned /// * ``assignment[2]`` is the slot at which the committee is assigned /// Return None if no assignment. /// </summary> public CommitteeAssignment GetCommitteeAssignment(BeaconState state, Epoch epoch, ValidatorIndex validatorIndex) { Epoch nextEpoch = _beaconStateAccessor.GetCurrentEpoch(state) + Epoch.One; if (epoch > nextEpoch) { throw new ArgumentOutOfRangeException(nameof(epoch), epoch, $"Committee epoch cannot be greater than next epoch {nextEpoch}."); } TimeParameters timeParameters = _timeParameterOptions.CurrentValue; Slot startSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(epoch); ulong endSlot = startSlot + timeParameters.SlotsPerEpoch; for (Slot slot = startSlot; slot < endSlot; slot += Slot.One) { ulong committeeCount = _beaconStateAccessor.GetCommitteeCountAtSlot(state, slot); for (CommitteeIndex index = CommitteeIndex.Zero; index < new CommitteeIndex(committeeCount); index += CommitteeIndex.One) { IReadOnlyList <ValidatorIndex> committee = _beaconStateAccessor.GetBeaconCommittee(state, slot, index); if (committee.Contains(validatorIndex)) { CommitteeAssignment committeeAssignment = new CommitteeAssignment(committee, index, slot); return(committeeAssignment); } } } return(CommitteeAssignment.None); }
private void CheckHistoricalSlots(IStore store, IReadOnlyList <Hash32> historicalBlockRoots, Slot fromSlot, Slot startSlot, ValidatorIndex validatorIndex, ref Slot attestationSlot, ref CommitteeIndex attestationCommitteeIndex, ref Slot blockProposalSlot) { TimeParameters timeParameters = _timeParameterOptions.CurrentValue; Slot previousSlot = fromSlot; while (true) { previousSlot -= Slot.One; int index = (int)(previousSlot % timeParameters.SlotsPerHistoricalRoot); Hash32 previousRoot = historicalBlockRoots[index]; if (!store.TryGetBlockState(previousRoot, out BeaconState? previousState)) { throw new Exception($"Historical state {previousRoot} for slot {previousSlot} not found."); } CheckStateDuty(previousState !, validatorIndex, ref attestationSlot, ref attestationCommitteeIndex, ref blockProposalSlot); if (previousSlot <= startSlot || (attestationSlot != Slot.None && blockProposalSlot != Slot.None)) { break; } } }