public async Task <Gwei> GetLatestAttestingBalanceAsync(IStore store, Hash32 root) { // NOTE: This method should probably live in IStore, for various efficient implementations. Checkpoint justifiedCheckpoint = store.JustifiedCheckpoint; BeaconState state = (await store.GetCheckpointStateAsync(justifiedCheckpoint, true).ConfigureAwait(false)) !; Epoch currentEpoch = _beaconStateAccessor.GetCurrentEpoch(state); IList <ValidatorIndex> activeIndexes = _beaconStateAccessor.GetActiveValidatorIndices(state, currentEpoch); BeaconBlock rootBlock = await store.GetBlockAsync(root).ConfigureAwait(false); Slot rootSlot = rootBlock !.Slot; Gwei balance = Gwei.Zero; foreach (ValidatorIndex index in activeIndexes) { LatestMessage?latestMessage = await store.GetLatestMessageAsync(index, false); if (latestMessage != null) { Hash32 ancestor = await GetAncestorAsync(store, latestMessage.Root, rootSlot); if (ancestor == root) { Validator validator = state.Validators[(int)index]; balance += validator.EffectiveBalance; } } } return(balance); }
private static Gwei DecodeGwei(Span <byte> span, ref int offset) { Gwei gwei = new Gwei(BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(offset))); offset += Gwei.SszLength; return(gwei); }
public async Task <Hash32> GetHeadAsync(IStore store) { // NOTE: This method should probably live in a separate object, for different implementations, possibly part of Store (for efficiency). // Execute the LMD-GHOST fork choice Hash32 head = store.JustifiedCheckpoint.Root; Slot justifiedSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(store.JustifiedCheckpoint.Epoch); while (true) { List <Tuple <Hash32, Gwei> > childKeysWithBalances = new List <Tuple <Hash32, Gwei> >(); await foreach (Hash32 childKey in store.GetChildKeysAfterSlotAsync(head, justifiedSlot) .ConfigureAwait(false)) { Gwei balance = await GetLatestAttestingBalanceAsync(store, childKey).ConfigureAwait(false); childKeysWithBalances.Add(Tuple.Create(childKey, balance)); } if (childKeysWithBalances.Count == 0) { return(head); } head = childKeysWithBalances .OrderByDescending(x => x.Item2) .ThenByDescending(x => x.Item1) .Select(x => x.Item1) .First(); } }
/// <summary> /// Increase the validator balance at index ``index`` by ``delta``. /// </summary> public void IncreaseBalance(BeaconState state, ValidatorIndex index, Gwei delta) { Gwei balance = state.Balances[(int)index]; Gwei newBalance = balance + delta; state.SetBalance(index, newBalance); }
public DepositData(BlsPublicKey publicKey, Bytes32 withdrawalCredentials, Gwei amount, BlsSignature signature) { PublicKey = publicKey; WithdrawalCredentials = withdrawalCredentials; Amount = amount; Signature = signature; // Signing over DepositMessage }
public DepositData(BlsPublicKey publicKey, Hash32 withdrawalCredentials, Gwei amount) { PublicKey = publicKey; WithdrawalCredentials = withdrawalCredentials; Amount = amount; Signature = new BlsSignature(); }
/// <summary> /// Return from ``indices`` a random index sampled by effective balance. /// </summary> public ValidatorIndex ComputeProposerIndex(BeaconState state, IList <ValidatorIndex> indices, Bytes32 seed) { if (!indices.Any()) { throw new ArgumentException("Indices can not be empty", nameof(indices)); } ulong indexCount = (ulong)indices.Count; ValidatorIndex index = 0UL; Span <byte> randomInputBytes = stackalloc byte[40]; seed.AsSpan().CopyTo(randomInputBytes); while (true) { ValidatorIndex initialValidatorIndex = (ValidatorIndex)(index % indexCount); ValidatorIndex shuffledIndex = ComputeShuffledIndex(initialValidatorIndex, indexCount, seed); ValidatorIndex candidateIndex = indices[(int)shuffledIndex]; BinaryPrimitives.WriteUInt64LittleEndian(randomInputBytes.Slice(32), index / 32); Bytes32 randomHash = _cryptographyService.Hash(randomInputBytes); byte random = randomHash.AsSpan()[(int)(index % 32)]; Gwei effectiveBalance = state.Validators[(int)candidateIndex].EffectiveBalance; if ((effectiveBalance * byte.MaxValue) >= (_gweiValueOptions.CurrentValue.MaximumEffectiveBalance * random)) { return(candidateIndex); } index++; } }
public EffectiveBalanceCase(Gwei preEffective, Gwei balance, Gwei postEffective, string name) { PreEffective = preEffective; Balance = balance; PostEffective = postEffective; Name = name; }
public async Task <Gwei> GetLatestAttestingBalanceAsync(IStore store, Root root) { Checkpoint justifiedCheckpoint = store.JustifiedCheckpoint; BeaconState state = (await store.GetCheckpointStateAsync(justifiedCheckpoint, true).ConfigureAwait(false)) !; Epoch currentEpoch = _beaconStateAccessor.GetCurrentEpoch(state); IList <ValidatorIndex> activeIndexes = _beaconStateAccessor.GetActiveValidatorIndices(state, currentEpoch); SignedBeaconBlock rootBlock = await store.GetSignedBlockAsync(root).ConfigureAwait(false); Slot rootSlot = rootBlock !.Message.Slot; Gwei balance = Gwei.Zero; foreach (ValidatorIndex index in activeIndexes) { LatestMessage?latestMessage = await store.GetLatestMessageAsync(index, false); if (latestMessage != null) { Root ancestor = await store.GetAncestorAsync(latestMessage.Root, rootSlot); if (ancestor == root) { Validator validator = state.Validators[(int)index]; balance += validator.EffectiveBalance; } } } return(balance); }
public Gwei GetLatestAttestingBalance(IStore store, Hash32 root) { if (!store.TryGetCheckpointState(store.JustifiedCheckpoint, out var storedState)) { throw new Exception($"Not able to get checkpoint state {store.JustifiedCheckpoint}"); } var state = storedState !; var currentEpoch = _beaconStateAccessor.GetCurrentEpoch(state); var activeIndexes = _beaconStateAccessor.GetActiveValidatorIndices(state, currentEpoch); if (!store.TryGetBlock(root, out var rootBlock)) { throw new Exception($"Not ble to find block {root}"); } Slot rootSlot = rootBlock !.Slot; Gwei balance = Gwei.Zero; foreach (ValidatorIndex index in activeIndexes) { if (store.TryGetLatestMessage(index, out var latestMessage)) { var ancestor = GetAncestor(store, latestMessage !.Root, rootSlot); if (ancestor == root) { var validator = state.Validators[(int)index]; balance += validator.EffectiveBalance; } } } return(balance); }
// 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) { var gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; var beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); var preValidatorCount = state.Validators.Count; var 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) { var 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); } var balance = TestState.GetBalance(state, validatorIndex); var expectedBalance = preBalance + deposit.Data.Amount; balance.ShouldBe(expectedBalance); var 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 void MaximumPenalties() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); StateListLengths stateListLengths = testServiceProvider.GetService <IOptions <StateListLengths> >().Value; BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); int slashedCount = (state.Validators.Count / 3) + 1; Epoch currentEpoch = beaconStateAccessor.GetCurrentEpoch(state); Epoch outEpoch = currentEpoch + new Epoch((ulong)stateListLengths.EpochsPerSlashingsVector / 2); var slashedIndices = Enumerable.Range(0, slashedCount).ToList(); SlashValidators(testServiceProvider, state, slashedIndices, Enumerable.Repeat(outEpoch, slashedCount)); Gwei totalBalance = beaconStateAccessor.GetTotalActiveBalance(state); Gwei totalPenalties = state.Slashings.Aggregate(Gwei.Zero, (accumulator, x) => accumulator + x); (totalBalance / 3).ShouldBeLessThanOrEqualTo(totalPenalties); // Act RunProcessSlashings(testServiceProvider, state); // Assert foreach (int index in slashedIndices) { state.Balances[index].ShouldBe(Gwei.Zero, $"Incorrect balance {index}"); } }
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 BeaconState InitializeBeaconStateFromEth1(Bytes32 eth1BlockHash, ulong eth1Timestamp, IList <Deposit> deposits) { if (_logger.IsInfo()) { Log.InitializeBeaconState(_logger, eth1BlockHash, eth1Timestamp, deposits.Count, null); } InitialValues initialValues = _initialValueOptions.CurrentValue; GweiValues gweiValues = _gweiValueOptions.CurrentValue; TimeParameters timeParameters = _timeParameterOptions.CurrentValue; StateListLengths stateListLengths = _stateListLengthOptions.CurrentValue; Fork fork = new Fork(initialValues.GenesisForkVersion, initialValues.GenesisForkVersion, _chainConstants.GenesisEpoch); ulong genesisTime = eth1Timestamp - (eth1Timestamp % timeParameters.MinimumGenesisDelay) + (2 * timeParameters.MinimumGenesisDelay); Eth1Data eth1Data = new Eth1Data(Root.Zero, (ulong)deposits.Count, eth1BlockHash); Root emptyBlockBodyRoot = _cryptographyService.HashTreeRoot(BeaconBlockBody.Zero); BeaconBlockHeader latestBlockHeader = new BeaconBlockHeader(emptyBlockBodyRoot); Bytes32[] randaoMixes = Enumerable.Repeat(eth1BlockHash, (int)stateListLengths.EpochsPerHistoricalVector) .ToArray(); BeaconState state = new BeaconState(genesisTime, fork, eth1Data, latestBlockHeader, randaoMixes, timeParameters.SlotsPerHistoricalRoot, stateListLengths.EpochsPerHistoricalVector, stateListLengths.EpochsPerSlashingsVector, _chainConstants.JustificationBitsLength); // Process deposits List <DepositData> depositDataList = new List <DepositData>(); foreach (Deposit deposit in deposits) { depositDataList.Add(deposit.Data); Root depositRoot = _cryptographyService.HashTreeRoot(depositDataList); state.Eth1Data.SetDepositRoot(depositRoot); _beaconStateTransition.ProcessDeposit(state, deposit); } // Process activations for (int validatorIndex = 0; validatorIndex < state.Validators.Count; validatorIndex++) { Validator validator = state.Validators[validatorIndex]; Gwei balance = state.Balances[validatorIndex]; Gwei effectiveBalance = Gwei.Min(balance - (balance % gweiValues.EffectiveBalanceIncrement), gweiValues.MaximumEffectiveBalance); validator.SetEffectiveBalance(effectiveBalance); if (validator.EffectiveBalance == gweiValues.MaximumEffectiveBalance) { validator.SetEligible(_chainConstants.GenesisEpoch); validator.SetActive(_chainConstants.GenesisEpoch); } } return(state); }
public void ProcessDeposit(BeaconState state, Deposit deposit) { _logger.LogInformation(Event.ProcessDeposit, "Process block operation deposit {Deposit} for state {BeaconState}.", deposit, state); var gweiValues = _gweiValueOptions.CurrentValue; // Verify the Merkle branch var isValid = _beaconChainUtility.IsValidMerkleBranch( deposit.Data.HashTreeRoot(), deposit.Proof, _chainConstants.DepositContractTreeDepth + 1, // Add 1 for the 'List' length mix-in state.Eth1DepositIndex, state.Eth1Data.DepositRoot); if (!isValid) { throw new Exception($"Invalid Merle branch for deposit for validator poublic key {deposit.Data.PublicKey}"); } // Deposits must be processed in order state.IncreaseEth1DepositIndex(); var publicKey = deposit.Data.PublicKey; var amount = deposit.Data.Amount; var validatorPublicKeys = state.Validators.Select(x => x.PublicKey).ToList(); if (!validatorPublicKeys.Contains(publicKey)) { // Verify the deposit signature (proof of possession) for new validators // Note: The deposit contract does not check signatures. // Note: Deposits are valid across forks, thus the deposit domain is retrieved directly from 'computer_domain'. var domain = _beaconChainUtility.ComputeDomain(_signatureDomainOptions.CurrentValue.Deposit); if (!_cryptographyService.BlsVerify(publicKey, deposit.Data.SigningRoot(), deposit.Data.Signature, domain)) { return; } var effectiveBalance = Gwei.Min(amount - (amount % gweiValues.EffectiveBalanceIncrement), gweiValues.MaximumEffectiveBalance); var newValidator = new Validator( publicKey, deposit.Data.WithdrawalCredentials, effectiveBalance , _chainConstants.FarFutureEpoch, _chainConstants.FarFutureEpoch, _chainConstants.FarFutureEpoch, _chainConstants.FarFutureEpoch); state.AddValidatorWithBalance(newValidator, amount); } else { var index = (ValidatorIndex)(ulong)validatorPublicKeys.IndexOf(publicKey); _beaconStateMutator.IncreaseBalance(state, index, amount); } }
private DepositData BuildAndSignDepositData(ulong validatorIndex, Gwei amount, SignatureDomains signatureDomains) { InitialValues initialValues = _initialValueOptions.CurrentValue; byte[] privateKey = GeneratePrivateKey(validatorIndex); // Public Key BLSParameters blsParameters = new BLSParameters { PrivateKey = privateKey }; using BLS bls = BLS.Create(blsParameters); byte[] publicKeyBytes = new byte[BlsPublicKey.Length]; bls.TryExportBlsPublicKey(publicKeyBytes, out int publicKeyBytesWritten); BlsPublicKey publicKey = new BlsPublicKey(publicKeyBytes); // Withdrawal Credentials Bytes32 withdrawalCredentials = _crypto.Hash(publicKey.AsSpan()); withdrawalCredentials.Unwrap()[0] = initialValues.BlsWithdrawalPrefix; // Build deposit data DepositData depositData = new DepositData(publicKey, withdrawalCredentials, amount, BlsSignature.Zero); // Sign deposit data Domain domain = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit); DepositMessage depositMessage = new DepositMessage( depositData.PublicKey, depositData.WithdrawalCredentials, depositData.Amount); Root depositMessageRoot = _crypto.HashTreeRoot(depositMessage); Root depositDataSigningRoot = _beaconChainUtility.ComputeSigningRoot(depositMessageRoot, domain); byte[] signatureBytes = new byte[96]; bls.TrySignData(depositDataSigningRoot.AsSpan(), signatureBytes, out int bytesWritten); BlsSignature depositDataSignature = new BlsSignature(signatureBytes); depositData.SetSignature(depositDataSignature); if (_logger.IsEnabled(LogLevel.Debug)) { LogDebug.QuickStartAddValidator(_logger, validatorIndex, publicKey.ToString().Substring(0, 12), null); } return(depositData); }
/// <summary> /// Decrease the validator balance at index ``index`` by ``delta``, with underflow protection. /// </summary> public void DecreaseBalance(BeaconState state, ValidatorIndex index, Gwei delta) { Gwei balance = state.Balances[(int)index]; if (delta > balance) { state.SetBalance(index, Gwei.Zero); } else { Gwei newBalance = balance - delta; state.SetBalance(index, newBalance); } }
public static DepositData DecodeDepositData(Span <byte> span) { if (span.Length != Ssz.DepositDataLength) { ThrowSourceLength <DepositData>(span.Length, Ssz.DepositDataLength); } int offset = 0; BlsPublicKey publicKey = DecodeBlsPublicKey(span, ref offset); Hash32 withdrawalCredentials = DecodeSha256(span, ref offset); Gwei amount = DecodeGwei(span, ref offset); BlsSignature signature = DecodeBlsSignature(span, ref offset); DepositData container = new DepositData(publicKey, withdrawalCredentials, amount, signature); return(container); }
/// <summary> /// Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.) /// </summary> public Gwei GetTotalBalance(BeaconState state, IEnumerable <ValidatorIndex> validatorIndices) { Gwei total = Gwei.Zero; foreach (ValidatorIndex index in validatorIndices) { Validator validator = state.Validators[(int)index]; Gwei balance = validator.EffectiveBalance; total += balance; } if (total == Gwei.Zero) { return(new Gwei(1)); } return(total); }
/// <summary> /// Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.) /// </summary> public Gwei GetTotalBalance(BeaconState state, IEnumerable <ValidatorIndex> validatorIndices) { var total = new Gwei(0); foreach (var index in validatorIndices) { var validator = state.Validators[(int)(ulong)index]; var balance = validator.EffectiveBalance; total += balance; } if (total == new Gwei(0)) { return(new Gwei(1)); } return(total); }
public void NewDepositUnderMax() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); // fresh deposit = next validator index = validator appended to registry ValidatorIndex validatorIndex = new ValidatorIndex((ulong)state.Validators.Count); // effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement. GweiValues gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; Gwei amount = gweiValues.MaximumEffectiveBalance - new Gwei(1); Deposit deposit = TestDeposit.PrepareStateAndDeposit(testServiceProvider, state, validatorIndex, amount, Bytes32.Zero, signed: true); RunDepositProcessing(testServiceProvider, state, deposit, validatorIndex, expectValid: true, effective: true); }
public async Task <Root> GetHeadAsync(IStore store) { // NOTE: These functions have been moved here, instead of ForkChoice, because some of them may benefit // from direct looking in the storage mechanism (e.g. database) or have other ways to optimise based on // the actual storage used. // TODO: Several different implementations provided in spec, for efficiency // TODO: Also, should cache, i.e. will only change if store is updated (so should be easy to cache if in store) // Get filtered block tree that only includes viable branches IDictionary <Root, BeaconBlock> blocks = await GetFilteredBlockTreeAsync(store).ConfigureAwait(false); // Latest Message Driven - Greedy Heaviest Observed Subtree // Fresh Message Driven // Execute the LMD-GHOST fork choice Root head = store.JustifiedCheckpoint.Root; Slot justifiedSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(store.JustifiedCheckpoint.Epoch); while (true) { List <Tuple <Root, Gwei> > childKeysWithBalances = new List <Tuple <Root, Gwei> >(); foreach (KeyValuePair <Root, BeaconBlock> kvp in blocks) { if (kvp.Value.ParentRoot.Equals(head) && kvp.Value.Slot > justifiedSlot) { Gwei balance = await GetLatestAttestingBalanceAsync(store, kvp.Key).ConfigureAwait(false); childKeysWithBalances.Add(Tuple.Create(kvp.Key, balance)); } } if (childKeysWithBalances.Count == 0) { return(head); } // Sort by latest attesting balance with ties broken lexicographically head = childKeysWithBalances .OrderByDescending(x => x.Item2) .ThenByDescending(x => x.Item1) .Select(x => x.Item1) .First(); } }
public Validator( BlsPublicKey publicKey, Hash32 withdrawalCredentials, Gwei effectiveBalance, //bool slashed, Epoch activationEligibilityEpoch, Epoch activationEpoch, Epoch exitEpoch, Epoch withdrawableEpoch) { PublicKey = publicKey; WithdrawalCredentials = withdrawalCredentials; EffectiveBalance = effectiveBalance; ActivationEligibilityEpoch = activationEligibilityEpoch; ActivationEpoch = activationEpoch; ExitEpoch = exitEpoch; WithdrawableEpoch = withdrawableEpoch; }
public static Gwei[] DecodeGweis(Span <byte> span) { if (span.Length == 0) { return(Array.Empty <Gwei>()); } int count = span.Length / Ssz.GweiLength; Gwei[] result = new Gwei[count]; for (int i = 0; i < count; i++) { Span <byte> current = span.Slice(i * Ssz.GweiLength, Ssz.GweiLength); result[i] = DecodeGwei(current); } return(result); }
public BeaconState InitializeBeaconStateFromEth1(Hash32 eth1BlockHash, ulong eth1Timestamp, IEnumerable <Deposit> deposits) { _logger.LogDebug(Event.InitializeBeaconState, "Initialise beacon state from ETH1 block {Eth1BlockHash}, time {Eth1Timestamp}, with {DepositCount} deposits.", eth1BlockHash, eth1Timestamp, deposits.Count()); var gweiValues = _gweiValueOptions.CurrentValue; var initialValues = _initialValueOptions.CurrentValue; var timeParameters = _timeParameterOptions.CurrentValue; var stateListLengths = _stateListLengthOptions.CurrentValue; var genesisTime = eth1Timestamp - (eth1Timestamp % _chainConstants.SecondsPerDay) + (2 * _chainConstants.SecondsPerDay); var eth1Data = new Eth1Data((ulong)deposits.Count(), eth1BlockHash); var emptyBlockBody = new BeaconBlockBody(); var latestBlockHeader = new BeaconBlockHeader(emptyBlockBody.HashTreeRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue)); var state = new BeaconState(genesisTime, 0, eth1Data, latestBlockHeader, timeParameters.SlotsPerHistoricalRoot, stateListLengths.EpochsPerHistoricalVector, stateListLengths.EpochsPerSlashingsVector, _chainConstants.JustificationBitsLength); // Process deposits var depositDataList = new List <DepositData>(); foreach (var deposit in deposits) { depositDataList.Add(deposit.Data); var depositRoot = depositDataList.HashTreeRoot(_chainConstants.MaximumDepositContracts); state.Eth1Data.SetDepositRoot(depositRoot); _beaconStateTransition.ProcessDeposit(state, deposit); } // Process activations for (var validatorIndex = 0; validatorIndex < state.Validators.Count; validatorIndex++) { var validator = state.Validators[validatorIndex]; var balance = state.Balances[validatorIndex]; var effectiveBalance = Gwei.Min(balance - (balance % gweiValues.EffectiveBalanceIncrement), gweiValues.MaximumEffectiveBalance); validator.SetEffectiveBalance(effectiveBalance); if (validator.EffectiveBalance == gweiValues.MaximumEffectiveBalance) { validator.SetEligible(initialValues.GenesisEpoch); validator.SetActive(initialValues.GenesisEpoch); } } return(state); }
public static Validator DecodeValidator(Span <byte> span) { if (span.Length != Ssz.ValidatorLength) { ThrowSourceLength <Validator>(span.Length, Ssz.ValidatorLength); } int offset = 0; BlsPublicKey publicKey = DecodeBlsPublicKey(span, ref offset); Bytes32 withdrawalCredentials = DecodeBytes32(span, ref offset); Gwei effectiveBalance = DecodeGwei(span, ref offset); bool isSlashed = DecodeBool(span, ref offset); Epoch activationEligibilityEpoch = DecodeEpoch(span, ref offset); Epoch activationEpoch = DecodeEpoch(span, ref offset); Epoch exitEpoch = DecodeEpoch(span, ref offset); Epoch withdrawableEpoch = DecodeEpoch(span, ref offset); Validator container = new Validator(publicKey, withdrawalCredentials, effectiveBalance, isSlashed, activationEligibilityEpoch, activationEpoch, exitEpoch, withdrawableEpoch); return(container); }
public static Validator BuildMockValidator(ChainConstants chainConstants, InitialValues initialValues, GweiValues gweiValues, TimeParameters timeParameters, ulong validatorIndex, Gwei balance) { var publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); var publicKey = publicKeys[validatorIndex]; // insecurely use pubkey as withdrawal key if no credentials provided var withdrawalCredentialBytes = TestSecurity.Hash(publicKey.AsSpan()); withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix; var withdrawalCredentials = new Bytes32(withdrawalCredentialBytes); var validator = new Validator( publicKey, withdrawalCredentials, Gwei.Min(balance - balance % gweiValues.EffectiveBalanceIncrement, gweiValues.MaximumEffectiveBalance), false, chainConstants.FarFutureEpoch, chainConstants.FarFutureEpoch, chainConstants.FarFutureEpoch, chainConstants.FarFutureEpoch); return(validator); }
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); }
private Gwei GetLatestAttestingBalance(Hash32 root) { var state = CheckpointStates[JustifiedCheckpoint]; //var currentEpoch = GetCurrentEpoch(state); //var activeIndexes = GetActiveValidatorIndices(state, currentEpoch); var rootSlot = Blocks[root].Slot; var balance = new Gwei(0); /* * foreach (var index in activeIndexes) * { * if (LatestMessages.Contains(index)) * { * var latestMessage = LatestMessages[index]; * var ancestor = GetAncestor(latestMessage.Root, rootSlot); * if (ancestor == root) * { * balance += state.Validators[index].EffectiveBalance; * } * } * } */ return(balance); }
/// <summary> /// Slash the validator with index ``slashed_index``. /// </summary> public void SlashValidator(BeaconState state, ValidatorIndex slashedIndex, ValidatorIndex whistleblowerIndex) { 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); if (whistleblowerIndex == ValidatorIndex.None) { whistleblowerIndex = proposerIndex; } Gwei whistleblowerReward = validator.EffectiveBalance / rewardsAndPenalties.WhistleblowerRewardQuotient; Gwei proposerReward = whistleblowerReward / rewardsAndPenalties.ProposerRewardQuotient; IncreaseBalance(state, proposerIndex, proposerReward); IncreaseBalance(state, whistleblowerIndex, whistleblowerReward - proposerReward); }