public async Task ChainNoAttestations() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; // Initialization ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); IStore store = forkChoice.GetGenesisStore(state); // On receiving a block of `GENESIS_SLOT + 1` slot BeaconBlock block1 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block1); await AddBlockToStore(testServiceProvider, store, block1); // On receiving a block of next epoch BeaconBlock block2 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block2); await AddBlockToStore(testServiceProvider, store, block2); // Act Hash32 headRoot = await forkChoice.GetHeadAsync(store); // Assert Hash32 expectedRoot = cryptographyService.SigningRoot(block2); headRoot.ShouldBe(expectedRoot); }
public async Task GenesisHead() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; StateListLengths stateListLengths = testServiceProvider.GetService <IOptions <StateListLengths> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; JsonSerializerOptions options = new System.Text.Json.JsonSerializerOptions { WriteIndented = true }; options.ConfigureNethermindCore2(); string debugState = System.Text.Json.JsonSerializer.Serialize(state, options); // Initialization ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); IStore store = forkChoice.GetGenesisStore(state); // Act Hash32 headRoot = await forkChoice.GetHeadAsync(store); // Assert Hash32 stateRoot = cryptographyService.HashTreeRoot(state); BeaconBlock genesisBlock = new BeaconBlock(stateRoot); Hash32 expectedRoot = cryptographyService.SigningRoot(genesisBlock); headRoot.ShouldBe(expectedRoot); }
public async Task ShouldReturnDefaultForkVersion() { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); testServiceCollection.AddSingleton <IEth1DataProvider>(Substitute.For <IEth1DataProvider>()); testServiceCollection.AddSingleton <IOperationPool>(Substitute.For <IOperationPool>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state _ = forkChoice.GetGenesisStore(state); // Act IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); beaconNode.ShouldBeOfType(typeof(BeaconNodeFacade)); Core2.Containers.Fork fork = await beaconNode.GetNodeForkAsync(CancellationToken.None); // Assert fork.Epoch.ShouldBe(Epoch.Zero); fork.CurrentVersion.ShouldBe(new ForkVersion()); fork.PreviousVersion.ShouldBe(new ForkVersion()); }
public QuickStart(ILogger <QuickStart> logger, ChainConstants chainConstants, IOptionsMonitor <MiscellaneousParameters> miscellaneousParameterOptions, IOptionsMonitor <GweiValues> gweiValueOptions, IOptionsMonitor <InitialValues> initialValueOptions, IOptionsMonitor <TimeParameters> timeParameterOptions, IOptionsMonitor <StateListLengths> stateListLengthOptions, IOptionsMonitor <MaxOperationsPerBlock> maxOperationsPerBlockOptions, IOptionsMonitor <SignatureDomains> signatureDomainOptions, IOptionsMonitor <QuickStartParameters> quickStartParameterOptions, ICryptographyService cryptographyService, BeaconChainUtility beaconChainUtility, Genesis beaconChain, ForkChoice forkChoice) { _logger = logger; _chainConstants = chainConstants; _miscellaneousParameterOptions = miscellaneousParameterOptions; _gweiValueOptions = gweiValueOptions; _initialValueOptions = initialValueOptions; _timeParameterOptions = timeParameterOptions; _stateListLengthOptions = stateListLengthOptions; _maxOperationsPerBlockOptions = maxOperationsPerBlockOptions; _signatureDomainOptions = signatureDomainOptions; _quickStartParameterOptions = quickStartParameterOptions; _cryptographyService = cryptographyService; _beaconChainUtility = beaconChainUtility; _beaconChain = beaconChain; _forkChoice = forkChoice; }
public async Task OnAttestationPreviousEpoch() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); InitialValues initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Initialization IStore store = forkChoice.GetGenesisStore(state); ulong time = store.Time + timeParameters.SecondsPerSlot * (ulong)timeParameters.SlotsPerEpoch; await forkChoice.OnTickAsync(store, time); BeaconBlock block = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block); // Store block in store await forkChoice.OnBlockAsync(store, block); Attestation attestation = TestAttestation.GetValidAttestation(testServiceProvider, state, block.Slot, CommitteeIndex.None, signed: true); attestation.Data.Target.Epoch.ShouldBe(initialValues.GenesisEpoch); BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); Slot currentSlot = forkChoice.GetCurrentSlot(store); Epoch currentEpoch = beaconChainUtility.ComputeEpochAtSlot(currentSlot); currentEpoch.ShouldBe(initialValues.GenesisEpoch + Epoch.One); await RunOnAttestation(testServiceProvider, state, store, attestation, expectValid : true); }
private async Task RunOnAttestation(IServiceProvider testServiceProvider, BeaconState state, IStore store, Attestation attestation, bool expectValid) { MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); if (!expectValid) { Should.Throw <Exception>(async() => { await forkChoice.OnAttestationAsync(store, attestation); }); return; } BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); IndexedAttestation indexedAttestation = beaconStateAccessor.GetIndexedAttestation(state, attestation); await forkChoice.OnAttestationAsync(store, attestation); IEnumerable <ValidatorIndex> attestingIndices = beaconStateAccessor.GetAttestingIndices(state, attestation.Data, attestation.AggregationBits); ValidatorIndex firstAttestingIndex = attestingIndices.First(); LatestMessage latestMessage = (await store.GetLatestMessageAsync(firstAttestingIndex, true)) !; latestMessage.Epoch.ShouldBe(attestation.Data.Target.Epoch); latestMessage.Root.ShouldBe(attestation.Data.BeaconBlockRoot); }
public async Task TestValidators80DutiesForEpochZeroHaveExactlyOneProposerPerSlot() { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); testServiceCollection.AddSingleton <IEth1DataProvider>(Substitute.For <IEth1DataProvider>()); testServiceCollection.AddSingleton <IOperationPool>(Substitute.For <IOperationPool>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state _ = forkChoice.GetGenesisStore(state); TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; int numberOfValidators = state.Validators.Count; Console.WriteLine("Number of validators: {0}", numberOfValidators); BlsPublicKey[] publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); byte[][] privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); for (int index = 0; index < numberOfValidators; index++) { Console.WriteLine("[{0}] priv:{1} pub:{2}", index, "0x" + BitConverter.ToString(privateKeys[index]).Replace("-", ""), publicKeys[index]); } // Act Epoch targetEpoch = new Epoch(0); IEnumerable <BlsPublicKey> validatorPublicKeys = publicKeys.Take(numberOfValidators); IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); beaconNode.ShouldBeOfType(typeof(BeaconNodeFacade)); int validatorDutyIndex = 0; List <ValidatorDuty> validatorDuties = new List <ValidatorDuty>(); await foreach (ValidatorDuty validatorDuty in beaconNode.ValidatorDutiesAsync(validatorPublicKeys, targetEpoch, CancellationToken.None)) { validatorDuties.Add(validatorDuty); Console.WriteLine("Index [{0}], Epoch {1}, Validator {2}, : attestation slot {3}, shard {4}, proposal slot {5}", validatorDutyIndex, targetEpoch, validatorDuty.ValidatorPublicKey, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); validatorDutyIndex++; } // Assert Dictionary <Slot, IGrouping <Slot, ValidatorDuty> > groupsByProposalSlot = validatorDuties .GroupBy(x => x.BlockProposalSlot) .ToDictionary(x => x.Key, x => x); groupsByProposalSlot[new Slot(0)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(1)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(2)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(3)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(4)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(5)].Count().ShouldBe(1); //groupsByProposalSlot[new Slot(6)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(7)].Count().ShouldBe(1); //groupsByProposalSlot[Slot.None].Count().ShouldBe(numberOfValidators - 7); }
private void AddAttestationToStore(IServiceProvider testServiceProvider, IStore store, Attestation attestation) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); if (!store.TryGetBlock(attestation.Data.BeaconBlockRoot, out BeaconBlock? parentBlock)) { throw new InvalidDataException("Cannot retrieve parent block"); } Hash32 parentSigningRoot = parentBlock !.SigningRoot(miscellaneousParameters, maxOperationsPerBlock); if (!store.TryGetBlockState(parentSigningRoot, out BeaconState? preState)) { throw new InvalidDataException("Cannot retrieve pre state"); } ulong blockTime = preState !.GenesisTime + (ulong)parentBlock !.Slot * timeParameters.SecondsPerSlot; ulong nextEpochTime = blockTime + (ulong)timeParameters.SlotsPerEpoch * timeParameters.SecondsPerSlot; if (store.Time < blockTime) { forkChoice.OnTick(store, blockTime); } forkChoice.OnAttestation(store, attestation); }
public void ProposerIndexForFirstTwoEpochsMustBeValid() { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state IStore store = forkChoice.GetGenesisStore(state); // Move forward time BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ulong time = state.GenesisTime + 1; ulong nextSlotTime = state.GenesisTime; ValidatorIndex maximumValidatorIndex = new ValidatorIndex((ulong)state.Validators.Count - 1); ValidatorIndex validatorIndex0 = beaconStateAccessor.GetBeaconProposerIndex(state); Console.WriteLine("Slot {0}, time {1} = proposer index {2}", state.Slot, time, validatorIndex0); validatorIndex0.ShouldBeLessThanOrEqualTo(maximumValidatorIndex); List <ValidatorIndex> proposerIndexes = new List <ValidatorIndex>(); proposerIndexes.Add(validatorIndex0); for (int slotIndex = 1; slotIndex <= 16; slotIndex++) { // Slot 1 nextSlotTime = nextSlotTime + timeParameters.SecondsPerSlot; while (time < nextSlotTime) { forkChoice.OnTick(store, time); time++; } forkChoice.OnTick(store, time); time++; BeaconBlock block = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block); forkChoice.OnBlock(store, block); forkChoice.OnTick(store, time); time++; ValidatorIndex validatorIndex = beaconStateAccessor.GetBeaconProposerIndex(state); Console.WriteLine("Slot {0}, time {1} = proposer index {2}", state.Slot, time, validatorIndex); validatorIndex.ShouldBeLessThanOrEqualTo(maximumValidatorIndex); proposerIndexes.Add(validatorIndex); } for (var slotIndex = 0; slotIndex < proposerIndexes.Count; slotIndex++) { ValidatorIndex proposerIndex = proposerIndexes[slotIndex]; Validator proposer = state.Validators[(int)(ulong)proposerIndex]; Console.WriteLine("Slot {0} = proposer index {1}, public key {2}", slotIndex, proposerIndex, proposer.PublicKey); } }
public async Task ValidatorDutyAtSpecificTime(ulong targetTime, string publicKey, ulong epoch, ulong attestationSlot, ulong attestationShard, ulong?blockProposalSlot) { // NOTE: Current algorithm for GetBeaconProposerIndex() someimtes allocates multiple proposal slots in an epoch, e.g. above index 23 gets slot 2 and 6 // It could be an error in the algorithm (need to check; domain type could be wrong), or due to the pre-shard algorithm. // The algorithm before shards were removed was different, so maybe ignore for now, implement phase 1 (with shards), and worry about it then. // This test for now will simply detect if things unintentionally change. // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state IStore store = forkChoice.GetGenesisStore(state); // Move forward time TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; for (ulong timeSinceGenesis = 1; timeSinceGenesis <= targetTime; timeSinceGenesis++) { ulong time = state.GenesisTime + timeSinceGenesis; await forkChoice.OnTickAsync(store, time); if (timeSinceGenesis % timeParameters.SecondsPerSlot == 0) { BeaconBlock block = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block); await forkChoice.OnBlockAsync(store, block); } } Console.WriteLine(""); Console.WriteLine("***** State advanced to slot {0}, time {1}, ready to start tests *****", state.Slot, store.Time); Console.WriteLine(""); // Act ValidatorAssignments validatorAssignments = testServiceProvider.GetService <ValidatorAssignments>(); BlsPublicKey validatorPublicKey = new BlsPublicKey(publicKey); Epoch targetEpoch = new Epoch(epoch); ValidatorDuty validatorDuty = await validatorAssignments.GetValidatorDutyAsync(validatorPublicKey, targetEpoch); Console.WriteLine("Validator {0}, epoch {1}: attestation slot {2}, shard {3}, proposal slot {4}", validatorPublicKey, targetEpoch, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); // Assert validatorDuty.ValidatorPublicKey.ShouldBe(validatorPublicKey); Slot expectedBlockProposalSlot = blockProposalSlot.HasValue ? new Slot(blockProposalSlot.Value) : Slot.None; Slot expectedAttestationSlot = new Slot(attestationSlot); Shard expectedAttestationShard = new Shard(attestationShard); validatorDuty.BlockProposalSlot.ShouldBe(expectedBlockProposalSlot); validatorDuty.AttestationSlot.ShouldBe(expectedAttestationSlot); validatorDuty.AttestationShard.ShouldBe(expectedAttestationShard); }
public async Task GenesisWithEmptyParametersTimeShouldReject() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); IOptionsMonitor <MiscellaneousParameters> miscellaneousParameterOptions = testServiceProvider.GetService <IOptionsMonitor <MiscellaneousParameters> >(); IOptionsMonitor <GweiValues> gweiValueOptions = testServiceProvider.GetService <IOptionsMonitor <GweiValues> >(); IOptionsMonitor <InitialValues> initialValueOptions = testServiceProvider.GetService <IOptionsMonitor <InitialValues> >(); IOptionsMonitor <TimeParameters> timeParameterOptions = testServiceProvider.GetService <IOptionsMonitor <TimeParameters> >(); IOptionsMonitor <StateListLengths> stateListLengthOptions = testServiceProvider.GetService <IOptionsMonitor <StateListLengths> >(); IOptionsMonitor <RewardsAndPenalties> rewardsAndPenaltiesOptions = testServiceProvider.GetService <IOptionsMonitor <RewardsAndPenalties> >(); IOptionsMonitor <MaxOperationsPerBlock> maxOperationsPerBlockOptions = testServiceProvider.GetService <IOptionsMonitor <MaxOperationsPerBlock> >(); IOptionsMonitor <ForkChoiceConfiguration> forkChoiceConfigurationOptions = testServiceProvider.GetService <IOptionsMonitor <ForkChoiceConfiguration> >(); IOptionsMonitor <SignatureDomains> signatureDomainOptions = testServiceProvider.GetService <IOptionsMonitor <SignatureDomains> >(); miscellaneousParameterOptions.CurrentValue.MinimumGenesisActiveValidatorCount = 2; LoggerFactory loggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider(TestOptionsMonitor.Create(new ConsoleLoggerOptions())) }); ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); BeaconChainUtility beaconChainUtility = new BeaconChainUtility(loggerFactory.CreateLogger <BeaconChainUtility>(), miscellaneousParameterOptions, gweiValueOptions, timeParameterOptions, cryptographyService); BeaconStateAccessor beaconStateAccessor = new BeaconStateAccessor(miscellaneousParameterOptions, initialValueOptions, timeParameterOptions, stateListLengthOptions, signatureDomainOptions, cryptographyService, beaconChainUtility); BeaconStateMutator beaconStateMutator = new BeaconStateMutator(chainConstants, timeParameterOptions, stateListLengthOptions, rewardsAndPenaltiesOptions, beaconChainUtility, beaconStateAccessor); BeaconStateTransition beaconStateTransition = new BeaconStateTransition(loggerFactory.CreateLogger <BeaconStateTransition>(), chainConstants, miscellaneousParameterOptions, gweiValueOptions, initialValueOptions, timeParameterOptions, stateListLengthOptions, rewardsAndPenaltiesOptions, maxOperationsPerBlockOptions, signatureDomainOptions, cryptographyService, beaconChainUtility, beaconStateAccessor, beaconStateMutator); BeaconNode.Genesis beaconChain = new BeaconNode.Genesis(loggerFactory.CreateLogger <BeaconNode.Genesis>(), chainConstants, miscellaneousParameterOptions, gweiValueOptions, initialValueOptions, timeParameterOptions, stateListLengthOptions, maxOperationsPerBlockOptions, cryptographyService, beaconStateAccessor, beaconStateTransition); MemoryStoreProvider storeProvider = new MemoryStoreProvider(loggerFactory, timeParameterOptions); ForkChoice forkChoice = new ForkChoice(loggerFactory.CreateLogger <ForkChoice>(), miscellaneousParameterOptions, initialValueOptions, timeParameterOptions, stateListLengthOptions, maxOperationsPerBlockOptions, forkChoiceConfigurationOptions, signatureDomainOptions, cryptographyService, beaconChainUtility, beaconStateAccessor, beaconStateTransition, storeProvider); ChainStart chainStart = new ChainStart(loggerFactory.CreateLogger <ChainStart>(), beaconChain, forkChoice); // Act Hash32 eth1BlockHash = Hash32.Zero; ulong eth1Timestamp = 106185600uL; // 1973-05-14 Deposit[] deposits = Array.Empty <Deposit>(); bool success = await chainStart.TryGenesisAsync(eth1BlockHash, eth1Timestamp, deposits); // Assert success.ShouldBeFalse(); }
public async Task ShorterChainButHeavierWeight() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; // Initialization ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); IStore store = forkChoice.GetGenesisStore(state); BeaconState genesisState = BeaconState.Clone(state); // build longer tree Hash32 longRoot = default; BeaconState longState = BeaconState.Clone(genesisState); for (int i = 0; i < 3; i++) { BeaconBlock longBlock = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, longState, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, longState, longBlock); await AddBlockToStore(testServiceProvider, store, longBlock); if (i == 2) { longRoot = cryptographyService.SigningRoot(longBlock); } } // build short tree BeaconState shortState = BeaconState.Clone(genesisState); BeaconBlock shortBlock = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, shortState, signed: true); shortBlock.Body.SetGraffiti(new Bytes32(Enumerable.Repeat((byte)0x42, 32).ToArray())); TestBlock.SignBlock(testServiceProvider, shortState, shortBlock, ValidatorIndex.None); TestState.StateTransitionAndSignBlock(testServiceProvider, shortState, shortBlock); await AddBlockToStore(testServiceProvider, store, shortBlock); Attestation shortAttestation = TestAttestation.GetValidAttestation(testServiceProvider, shortState, shortBlock.Slot, CommitteeIndex.None, signed: true); await AddAttestationToStore(testServiceProvider, store, shortAttestation); // Act Hash32 headRoot = await forkChoice.GetHeadAsync(store); // Assert Hash32 expectedRoot = cryptographyService.SigningRoot(shortBlock); headRoot.ShouldBe(expectedRoot); headRoot.ShouldNotBe(longRoot); }
public async Task TestValidators80DutiesForEpochOneHaveExactlyOneProposerPerSlot() { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); testServiceCollection.AddSingleton <IEth1DataProvider>(Substitute.For <IEth1DataProvider>()); testServiceCollection.AddSingleton <IOperationPool>(Substitute.For <IOperationPool>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state _ = forkChoice.GetGenesisStore(state); TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; int numberOfValidators = state.Validators.Count; Console.WriteLine("Number of validators: {0}", numberOfValidators); BlsPublicKey[] publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); // Act Epoch targetEpoch = new Epoch(1); var validatorPublicKeys = publicKeys.Take(numberOfValidators); IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); beaconNode.ShouldBeOfType(typeof(BeaconNodeFacade)); var validatorDuties = await beaconNode.ValidatorDutiesAsync(validatorPublicKeys, targetEpoch); for (var index = 0; index < validatorDuties.Count; index++) { ValidatorDuty validatorDuty = validatorDuties[index]; Console.WriteLine("Index [{0}], Epoch {1}, Validator {2}, : attestation slot {3}, shard {4}, proposal slot {5}", index, targetEpoch, validatorDuty.ValidatorPublicKey, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); } // Assert Dictionary <Slot, IGrouping <Slot, ValidatorDuty> > groupsByProposalSlot = validatorDuties .GroupBy(x => x.BlockProposalSlot) .ToDictionary(x => x.Key, x => x); groupsByProposalSlot[new Slot(8)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(9)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(10)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(11)].Count().ShouldBe(1); //groupsByProposalSlot[new Slot(12)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(13)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(14)].Count().ShouldBe(1); groupsByProposalSlot[new Slot(15)].Count().ShouldBe(1); //groupsByProposalSlot[Slot.None].Count().ShouldBe(numberOfValidators - 8); }
public MockedEth1DataProvider(IOptionsMonitor <TimeParameters> timeParameterOptions, IOptionsMonitor <HonestValidatorConstants> honestValidatorConstantOptions, ICryptographyService cryptographyService, BeaconStateAccessor beaconStateAccessor, ForkChoice forkChoice, IStoreProvider storeProvider) { _timeParameterOptions = timeParameterOptions; _honestValidatorConstantOptions = honestValidatorConstantOptions; _cryptographyService = cryptographyService; _beaconStateAccessor = beaconStateAccessor; _forkChoice = forkChoice; _storeProvider = storeProvider; }
private async Task AddBlockToStore(IServiceProvider testServiceProvider, IStore store, BeaconBlock block) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); BeaconState preState = await store.GetBlockStateAsync(block.ParentRoot); ulong blockTime = preState !.GenesisTime + (ulong)block.Slot * timeParameters.SecondsPerSlot; if (store.Time < blockTime) { await forkChoice.OnTickAsync(store, blockTime); } await forkChoice.OnBlockAsync(store, block); }
public async Task BasicValidatorDuty(string publicKey, ulong epoch, bool success, ulong attestationSlot, ulong attestationShard, ulong?blockProposalSlot) { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state _ = forkChoice.GetGenesisStore(state); // Act ValidatorAssignments validatorAssignments = testServiceProvider.GetService <ValidatorAssignments>(); BlsPublicKey validatorPublicKey = new BlsPublicKey(publicKey); Epoch targetEpoch = new Epoch(epoch); // failure expected if (!success) { Should.Throw <Exception>(async() => { ValidatorDuty validatorDuty = await validatorAssignments.GetValidatorDutyAsync(validatorPublicKey, targetEpoch); Console.WriteLine("Validator {0}, epoch {1}: attestation slot {2}, shard {3}, proposal slot {4}", validatorPublicKey, targetEpoch, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); }); return; } ValidatorDuty validatorDuty = await validatorAssignments.GetValidatorDutyAsync(validatorPublicKey, targetEpoch); Console.WriteLine("Validator {0}, epoch {1}: attestation slot {2}, shard {3}, proposal slot {4}", validatorPublicKey, targetEpoch, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); // Assert validatorDuty.ValidatorPublicKey.ShouldBe(validatorPublicKey); Slot expectedBlockProposalSlot = blockProposalSlot.HasValue ? new Slot(blockProposalSlot.Value) : Slot.None; Slot expectedAttestationSlot = new Slot(attestationSlot); Shard expectedAttestationShard = new Shard(attestationShard); validatorDuty.BlockProposalSlot.ShouldBe(expectedBlockProposalSlot); validatorDuty.AttestationSlot.ShouldBe(expectedAttestationSlot); validatorDuty.AttestationShard.ShouldBe(expectedAttestationShard); }
public async Task SplitTieBreakerNoAttestations() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; // Initialization ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); IStore store = forkChoice.GetGenesisStore(state); BeaconState genesisState = BeaconState.Clone(state); // block at slot 1 BeaconState block1State = BeaconState.Clone(genesisState); BeaconBlock block1 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, block1State, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, block1State, block1); await AddBlockToStore(testServiceProvider, store, block1); Hash32 block1Root = cryptographyService.SigningRoot(block1); // build short tree BeaconState block2State = BeaconState.Clone(genesisState); BeaconBlock block2 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, block2State, signed: true); block2.Body.SetGraffiti(new Bytes32(Enumerable.Repeat((byte)0x42, 32).ToArray())); TestBlock.SignBlock(testServiceProvider, block2State, block2, ValidatorIndex.None); TestState.StateTransitionAndSignBlock(testServiceProvider, block2State, block2); await AddBlockToStore(testServiceProvider, store, block2); Hash32 block2Root = cryptographyService.SigningRoot(block2); // Act Hash32 headRoot = await forkChoice.GetHeadAsync(store); // Assert Console.WriteLine("block1 {0}", block1Root); Console.WriteLine("block2 {0}", block2Root); Hash32 highestRoot = block1Root.CompareTo(block2Root) > 0 ? block1Root : block2Root; Console.WriteLine("highest {0}", highestRoot); headRoot.ShouldBe(highestRoot); }
private void AddBlockToStore(IServiceProvider testServiceProvider, IStore store, BeaconBlock block) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); if (!store.TryGetBlockState(block.ParentRoot, out BeaconState? preState)) { throw new InvalidDataException("Cannot retrieve pre state"); } ulong blockTime = preState !.GenesisTime + (ulong)block.Slot * timeParameters.SecondsPerSlot; if (store.Time < blockTime) { forkChoice.OnTick(store, blockTime); } forkChoice.OnBlock(store, block); }
public async Task BasicOnBlock() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true); BeaconState state = TestState.PrepareTestState(testServiceProvider); TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Initialization IStore store = forkChoice.GetGenesisStore(state); ulong time = 100uL; await forkChoice.OnTickAsync(store, time); store.Time.ShouldBe(time); // On receiving a block of `GENESIS_SLOT + 1` slot BeaconBlock block = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block); await RunOnBlock(testServiceProvider, store, block, expectValid : true); // On receiving a block of next epoch ulong time2 = time + timeParameters.SecondsPerSlot * (ulong)timeParameters.SlotsPerEpoch; await store.SetTimeAsync(time2); BeaconBlock block2 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true); Slot slot2 = (Slot)(block.Slot + timeParameters.SlotsPerEpoch); block2.SetSlot(slot2); TestBlock.SignBlock(testServiceProvider, state, block2, ValidatorIndex.None); TestState.StateTransitionAndSignBlock(testServiceProvider, state, block2); //var options = new System.Text.Json.JsonSerializerOptions { WriteIndented = true }; //options.AddCortexContainerConverters(); //var debugState = System.Text.Json.JsonSerializer.Serialize(state, options); await RunOnBlock(testServiceProvider, store, block2, expectValid : true); // Assert // TODO: add tests for justified_root and finalized_root }
public QuickStart(ILogger <QuickStart> logger, ChainConstants chainConstants, IOptionsMonitor <GweiValues> gweiValueOptions, IOptionsMonitor <InitialValues> initialValueOptions, IOptionsMonitor <SignatureDomains> signatureDomainOptions, IOptionsMonitor <QuickStartParameters> quickStartParameterOptions, ICryptographyService cryptographyService, BeaconChainUtility beaconChainUtility, Genesis beaconChain, ForkChoice forkChoice) { _logger = logger; _chainConstants = chainConstants; _gweiValueOptions = gweiValueOptions; _initialValueOptions = initialValueOptions; _signatureDomainOptions = signatureDomainOptions; _quickStartParameterOptions = quickStartParameterOptions; _cryptographyService = cryptographyService; _beaconChainUtility = beaconChainUtility; _beaconChain = beaconChain; _forkChoice = forkChoice; }
public void ValidatorShouldBeActiveAfterTestGenesis(ulong index, bool shouldBeActive) { // NOTE: Test genesis has SlotsPerEpoch (8) * 10 = 80 validators. // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state _ = forkChoice.GetGenesisStore(state); // Act ValidatorAssignments validatorAssignments = testServiceProvider.GetService <ValidatorAssignments>(); ValidatorIndex validatorIndex = new ValidatorIndex(index); bool validatorActive = validatorAssignments.CheckIfValidatorActive(state, validatorIndex); // Assert validatorActive.ShouldBe(shouldBeActive); }
private async Task AddAttestationToStore(IServiceProvider testServiceProvider, IStore store, Attestation attestation) { TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); BeaconBlock parentBlock = await store.GetBlockAsync(attestation.Data.BeaconBlockRoot); Hash32 parentSigningRoot = cryptographyService.SigningRoot(parentBlock); BeaconState preState = await store.GetBlockStateAsync(parentSigningRoot); ulong blockTime = preState.GenesisTime + (ulong)parentBlock.Slot * timeParameters.SecondsPerSlot; ulong nextEpochTime = blockTime + (ulong)timeParameters.SlotsPerEpoch * timeParameters.SecondsPerSlot; if (store.Time < blockTime) { await forkChoice.OnTickAsync(store, blockTime); } await forkChoice.OnAttestationAsync(store, attestation); }
private async Task RunOnBlock(IServiceProvider testServiceProvider, IStore store, BeaconBlock block, bool expectValid) { MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); if (!expectValid) { Should.Throw <Exception>(async() => { await forkChoice.OnBlockAsync(store, block); }); return; } await forkChoice.OnBlockAsync(store, block); Hash32 signingRoot = cryptographyService.SigningRoot(block); BeaconBlock storedBlock = await store.GetBlockAsync(signingRoot); storedBlock.ShouldBe(block); }
public async Task GenesisWithEmptyParametersTimeShouldReject() { // Arrange IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(); ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); IOptionsMonitor <MiscellaneousParameters> miscellaneousParameterOptions = testServiceProvider.GetService <IOptionsMonitor <MiscellaneousParameters> >(); IOptionsMonitor <GweiValues> gweiValueOptions = testServiceProvider.GetService <IOptionsMonitor <GweiValues> >(); IOptionsMonitor <InitialValues> initialValueOptions = testServiceProvider.GetService <IOptionsMonitor <InitialValues> >(); IOptionsMonitor <TimeParameters> timeParameterOptions = testServiceProvider.GetService <IOptionsMonitor <TimeParameters> >(); IOptionsMonitor <StateListLengths> stateListLengthOptions = testServiceProvider.GetService <IOptionsMonitor <StateListLengths> >(); IOptionsMonitor <RewardsAndPenalties> rewardsAndPenaltiesOptions = testServiceProvider.GetService <IOptionsMonitor <RewardsAndPenalties> >(); IOptionsMonitor <MaxOperationsPerBlock> maxOperationsPerBlockOptions = testServiceProvider.GetService <IOptionsMonitor <MaxOperationsPerBlock> >(); IOptionsMonitor <ForkChoiceConfiguration> forkChoiceConfigurationOptions = testServiceProvider.GetService <IOptionsMonitor <ForkChoiceConfiguration> >(); IOptionsMonitor <SignatureDomains> signatureDomainOptions = testServiceProvider.GetService <IOptionsMonitor <SignatureDomains> >(); IOptionsMonitor <InMemoryConfiguration> inMemoryConfigurationOptions = testServiceProvider.GetService <IOptionsMonitor <InMemoryConfiguration> >(); miscellaneousParameterOptions.CurrentValue.MinimumGenesisActiveValidatorCount = 2; LoggerFactory loggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider(Core2.Configuration.Static.OptionsMonitor <ConsoleLoggerOptions>()) }); ICryptographyService cryptographyService = testServiceProvider.GetService <ICryptographyService>(); IDepositStore depositStore = new DepositStore(cryptographyService, chainConstants); BeaconChainUtility beaconChainUtility = new BeaconChainUtility( loggerFactory.CreateLogger <BeaconChainUtility>(), chainConstants, miscellaneousParameterOptions, initialValueOptions, gweiValueOptions, timeParameterOptions, cryptographyService); BeaconStateAccessor beaconStateAccessor = new BeaconStateAccessor(chainConstants, miscellaneousParameterOptions, timeParameterOptions, stateListLengthOptions, signatureDomainOptions, cryptographyService, beaconChainUtility); BeaconStateMutator beaconStateMutator = new BeaconStateMutator(chainConstants, timeParameterOptions, stateListLengthOptions, rewardsAndPenaltiesOptions, beaconChainUtility, beaconStateAccessor); BeaconStateTransition beaconStateTransition = new BeaconStateTransition( loggerFactory.CreateLogger <BeaconStateTransition>(), chainConstants, gweiValueOptions, timeParameterOptions, stateListLengthOptions, rewardsAndPenaltiesOptions, maxOperationsPerBlockOptions, signatureDomainOptions, cryptographyService, beaconChainUtility, beaconStateAccessor, beaconStateMutator, depositStore); SimpleLatestMessageDrivenGreedyHeaviestObservedSubtree simpleLmdGhost = new SimpleLatestMessageDrivenGreedyHeaviestObservedSubtree( loggerFactory.CreateLogger <SimpleLatestMessageDrivenGreedyHeaviestObservedSubtree>(), chainConstants, beaconChainUtility, beaconStateAccessor); MemoryStore store = new MemoryStore(loggerFactory.CreateLogger <MemoryStore>(), inMemoryConfigurationOptions, new DataDirectory("data"), Substitute.For <IFileSystem>(), simpleLmdGhost, new StoreAccessor()); ForkChoice forkChoice = new ForkChoice(loggerFactory.CreateLogger <ForkChoice>(), chainConstants, miscellaneousParameterOptions, timeParameterOptions, maxOperationsPerBlockOptions, forkChoiceConfigurationOptions, signatureDomainOptions, cryptographyService, beaconChainUtility, beaconStateAccessor, beaconStateTransition); GenesisChainStart genesisChainStart = new GenesisChainStart(loggerFactory.CreateLogger <GenesisChainStart>(), chainConstants, miscellaneousParameterOptions, gweiValueOptions, initialValueOptions, timeParameterOptions, stateListLengthOptions, cryptographyService, store, beaconStateAccessor, beaconStateTransition, forkChoice, depositStore); // Act Bytes32 eth1BlockHash = Bytes32.Zero; ulong eth1Timestamp = 106185600uL; // 1973-05-14 bool success = await genesisChainStart.TryGenesisAsync(eth1BlockHash, eth1Timestamp); // Assert success.ShouldBeFalse(); }
public async Task FutureEpochValidatorDuty() { // Arrange IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); BeaconState state = TestState.PrepareTestState(testServiceProvider); ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>(); // Get genesis store initialise MemoryStoreProvider with the state IStore store = forkChoice.GetGenesisStore(state); // Move forward time TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; ulong time = state.GenesisTime + 1; ulong nextSlotTime = state.GenesisTime + timeParameters.SecondsPerSlot; // half way through epoch 4 ulong futureEpoch = 4uL; ulong slots = futureEpoch * timeParameters.SlotsPerEpoch + timeParameters.SlotsPerEpoch / 2; for (ulong slot = 1; slot < slots; slot++) { while (time < nextSlotTime) { forkChoice.OnTick(store, time); time++; } forkChoice.OnTick(store, time); time++; // Hash32 head = await forkChoice.GetHeadAsync(store); // store.TryGetBlockState(head, out BeaconState headState); BeaconState headState = state; BeaconBlock block = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, headState, signed: true); TestState.StateTransitionAndSignBlock(testServiceProvider, headState, block); forkChoice.OnBlock(store, block); nextSlotTime = nextSlotTime + timeParameters.SecondsPerSlot; } // halfway through slot ulong futureTime = nextSlotTime + timeParameters.SecondsPerSlot / 2; while (time < futureTime) { forkChoice.OnTick(store, time); time++; } Console.WriteLine(""); Console.WriteLine("***** State advanced to epoch {0}, slot {1}, time {2}, ready to start tests *****", futureEpoch, state.Slot, store.Time); Console.WriteLine(""); List <object?[]> data = FutureEpochValidatorDutyData().ToList(); for (int dataIndex = 0; dataIndex < data.Count; dataIndex++) { object?[] dataRow = data[dataIndex]; string publicKey = (string)dataRow[0] !; ulong epoch = (ulong)dataRow[1] !; bool success = (bool)dataRow[2] !; ulong attestationSlot = (ulong)dataRow[3] !; ulong attestationShard = (ulong)dataRow[4] !; ulong? blockProposalSlot = (ulong?)dataRow[5]; Console.WriteLine("** Test {0}, public key {1}, epoch {2}", dataIndex, publicKey, epoch); // Act ValidatorAssignments validatorAssignments = testServiceProvider.GetService <ValidatorAssignments>(); BlsPublicKey validatorPublicKey = new BlsPublicKey(publicKey); Epoch targetEpoch = new Epoch(epoch); // failure expected if (!success) { Should.Throw <Exception>(async() => { ValidatorDuty validatorDuty = await validatorAssignments.GetValidatorDutyAsync(validatorPublicKey, targetEpoch); Console.WriteLine( "Validator {0}, epoch {1}: attestation slot {2}, shard {3}, proposal slot {4}", validatorPublicKey, targetEpoch, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); }, $"Test {dataIndex}, public key {validatorPublicKey}, epoch {targetEpoch}"); continue; } ValidatorDuty validatorDuty = await validatorAssignments.GetValidatorDutyAsync(validatorPublicKey, targetEpoch); Console.WriteLine("Validator {0}, epoch {1}: attestation slot {2}, shard {3}, proposal slot {4}", validatorPublicKey, targetEpoch, validatorDuty.AttestationSlot, (ulong)validatorDuty.AttestationShard, validatorDuty.BlockProposalSlot); // Assert validatorDuty.ValidatorPublicKey.ShouldBe(validatorPublicKey, $"Test {dataIndex}, public key {validatorPublicKey}, epoch {targetEpoch}"); Slot expectedBlockProposalSlot = blockProposalSlot.HasValue ? new Slot(blockProposalSlot.Value) : Slot.None; Slot expectedAttestationSlot = new Slot(attestationSlot); Shard expectedAttestationShard = new Shard(attestationShard); validatorDuty.BlockProposalSlot.ShouldBe(expectedBlockProposalSlot, $"Test {dataIndex}, public key {validatorPublicKey}, epoch {targetEpoch}"); validatorDuty.AttestationSlot.ShouldBe(expectedAttestationSlot, $"Test {dataIndex}, public key {validatorPublicKey}, epoch {targetEpoch}"); validatorDuty.AttestationShard.ShouldBe(expectedAttestationShard, $"Test {dataIndex}, public key {validatorPublicKey}, epoch {targetEpoch}"); } }