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);
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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++;
            }
        }
Example #5
0
 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);
            }
        }
Example #7
0
 public static void Ize(out UInt256 root, ValidatorIndex container)
 {
     Ize(out root, container.Number);
 }
Example #8
0
 public VoluntaryExit(Epoch epoch, ValidatorIndex validatorIndex, BlsSignature signature)
 {
     Epoch          = epoch;
     ValidatorIndex = validatorIndex;
     Signature      = signature;
 }
Example #9
0
        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);
        }
Example #11
0
 private static void Encode(Span <byte> span, ValidatorIndex value, ref int offset)
 {
     BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(offset), value.Number);
     offset += Ssz.ValidatorIndexLength;
 }
Example #12
0
        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);
        }
Example #13
0
 public bool TryGetLatestMessage(ValidatorIndex validatorIndex, out LatestMessage latestMessage) => _latestMessages.TryGetValue(validatorIndex, out latestMessage);
Example #14
0
 public void SetLatestMessage(ValidatorIndex validatorIndex, LatestMessage latestMessage) => _latestMessages[validatorIndex] = latestMessage;
Example #15
0
        /// <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);
        }
Example #16
0
        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);
            }
        }
Example #17
0
        /// <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);
        }
Example #18
0
 public static void Encode(Span <byte> span, ValidatorIndex value)
 {
     Encode(span, value.Number);
 }
Example #19
0
        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);
        }
Example #20
0
 public void SetBalance(ValidatorIndex validatorIndex, Gwei balance) =>
 _balances[(int)validatorIndex] = balance;
Example #21
0
 public static Gwei GetBalance(BeaconState state, ValidatorIndex proposerIndex)
 {
     return(state.Balances[(int)(ulong)proposerIndex]);
 }
Example #22
0
        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));
 }
Example #24
0
        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));
        }
Example #25
0
 public Task SetLatestMessageAsync(ValidatorIndex validatorIndex, LatestMessage latestMessage)
 {
     _latestMessages[validatorIndex] = latestMessage;
     return(Task.CompletedTask);
 }
Example #26
0
        //    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);
        }
Example #27
0
        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);
        }
Example #29
0
        /// <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;
                }
            }
        }