/// <summary>
        /// Return the signature domain (fork version concatenated with domain type) of a message.
        /// </summary>
        public Domain GetDomain(BeaconState state, DomainType domainType, Epoch messageEpoch)
        {
            Epoch epoch;

            if (messageEpoch == Epoch.None)
            {
                epoch = GetCurrentEpoch(state);
            }
            else
            {
                epoch = messageEpoch;
            }

            ForkVersion forkVersion;

            if (epoch < state.Fork.Epoch)
            {
                forkVersion = state.Fork.PreviousVersion;
            }
            else
            {
                forkVersion = state.Fork.CurrentVersion;
            }

            return(_beaconChainUtility.ComputeDomain(domainType, forkVersion));
        }
        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);
            }
        }