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); } }
public static BeaconState CreateGenesisState(IServiceProvider testServiceProvider, ulong numberOfValidators) { ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); GweiValues gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value; InitialValues initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; StateListLengths stateListLengths = testServiceProvider.GetService <IOptions <StateListLengths> >().Value; ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); var eth1BlockHash = new Bytes32(Enumerable.Repeat((byte)0x42, 32).ToArray()); var state = new BeaconState( 0, new Core2.Containers.Fork(new ForkVersion(new byte[ForkVersion.Length]), new ForkVersion(new byte[ForkVersion.Length]), Epoch.Zero), new Eth1Data(Root.Zero, numberOfValidators, eth1BlockHash), //numberOfValidators, new BeaconBlockHeader(cryptographyService.HashTreeRoot(BeaconBlockBody.Zero)), Enumerable.Repeat(eth1BlockHash, (int)stateListLengths.EpochsPerHistoricalVector).ToArray(), timeParameters.SlotsPerHistoricalRoot, stateListLengths.EpochsPerHistoricalVector, stateListLengths.EpochsPerSlashingsVector, chainConstants.JustificationBitsLength ); // We directly insert in the initial validators, // as it is much faster than creating and processing genesis deposits for every single test case. for (var index = (ulong)0; index < numberOfValidators; index++) { var validator = BuildMockValidator(chainConstants, initialValues, gweiValues, timeParameters, index, gweiValues.MaximumEffectiveBalance); state.AddValidatorWithBalance(validator, gweiValues.MaximumEffectiveBalance); state.IncreaseEth1DepositIndex(); } // Process genesis activations foreach (var validator in state.Validators) { if (validator.EffectiveBalance >= gweiValues.MaximumEffectiveBalance) { validator.SetEligible(chainConstants.GenesisEpoch); validator.SetActive(chainConstants.GenesisEpoch); } } return(state); }