public async Task <BeaconBlock> NewBlockAsync(Slot slot, BlsSignature randaoReveal) { if (slot == Slot.Zero) { throw new ArgumentException("Can't generate new block for slot 0, as it is the genesis block."); } if (!_storeProvider.TryGetStore(out IStore? retrievedStore)) { throw new Exception("Beacon chain is currently syncing or waiting for genesis."); } IStore store = retrievedStore !; Slot previousSlot = slot - Slot.One; Hash32 head = await _forkChoice.GetHeadAsync(store); if (!store.TryGetBlock(head, out BeaconBlock? headBlock)) { throw new Exception($"Cannot find block for head root {head}"); } BeaconBlock parentBlock; BeaconState?retrievedParentState; Hash32 parentRoot; if (headBlock !.Slot > previousSlot) { // Requesting a block for a past slot? Hash32 ancestorSigningRoot = _forkChoice.GetAncestor(store, head, previousSlot); if (!store.TryGetBlock(ancestorSigningRoot, out BeaconBlock? retrievedParentBlock)) { throw new Exception($"Cannot find block for ancestor signing root {ancestorSigningRoot}"); } parentBlock = retrievedParentBlock !; if (!store.TryGetBlockState(ancestorSigningRoot, out retrievedParentState)) { throw new Exception($"Cannot find state for ancestor signing root {ancestorSigningRoot}"); } parentRoot = ancestorSigningRoot; }
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); }