# EPF Cohort 3 Dev Update 7 (pavignol)
Here are the Prysm validator features that I’ve been working on last week:
## Wrote the REST implementation for Validator's `GetDuties`
While the beacon REST API separates the duties retrieval in 3 distinct endpoints (`/eth/v1/validator/duties/attester/{epoch}`, `/eth/v1/validator/duties/proposer/{epoch}` and `/eth/v1/validator/duties/sync/{epoch}`), the Prysm gRPC API does everything in a single function called `GetDuties`. Moreover, `GetDuties` automatically retrieves the duties for the current epoch and the next epoch while the beacon REST API endpoints only target a single epoch at a time. For these reasons, this endpoint required combining a lot of endpoints together and massaging the data to make it fit into a single giant data structure containing all duties for `epoch` and `epoch+1`.
To make sure that the mapping respected all requirements of the gRPC API, a few rules and details have to be kept in mind:
1. Even validators that don't have duties for a given epoch should be returned if they were part of the request. This includes all validators in the `pending` state.
2. Attester and sync duties should be retrieved for both `epoch` and `epoch+1`
3. Proposer duties should only be retrieved for the current epoch (not `epoch+1`)
4. Since sync committee duties are an Altair feature, they should only be retrieved for `epoch>=AltairForkEpoch`.
5. For each validator, we have to return the array of validators that are part of the committee for the given epoch.
6. In addition to the duties, we also have to return the status of each validator .
With those rules in mind, the implementation was relatively straightforward:
1. Query the status of all validator public keys given in the input via the `/eth/v1/beacon/states/head/validators` endpoint to get the indices and status of each validator.
2. Query the list of committees for the given epoch and cache its validators in a `{committeeIndex, slot} -> validatorIndices` map
3. Query the list of attester duties for `epoch` and `epoch+1` and cache them in a `validatorIndex -> {committeeIndex, slot}` map
4. Query the list of sync duties for `epoch` and `epoch+1` (if `epoch>=AltairForkEpoch`) and cache the validator indices that have a sync dutie for this epoch in a set
5. Query the list of proposer duties for `epoch` and cache them in a `validatorIndex -> slot` map
6. Finally, for each index obtained in step 1:
6.1 If the attester duties map from step 3 has an entry for the current validator index, get its committee from the map obtained in step 2 and save the info in the output struct
6.2 If the sync duties set from step 4 has an entry for the current validator index, set the `IsSyncCommittee` value of the output struct to `true`
6.3 If the proposer duties map from step 5 has an entry for the current validator index, get its proposer slot from the map and set it in the output struct
Although the implementation is done and I have verified that it passes all tests, I haven't created a PR yet because it's dependent on 2 pending PRs:
- https://github.com/prysmaticlabs/prysm/pull/11786 (for the validator status endpoint)
- https://github.com/prysmaticlabs/prysm/pull/11804 (for the attester duties endpoint)
Also, implementing this endpoint revealed bugs in the implementation of all 3 duties endpoint, where an epoch would be erroneously rejected because it was in the future. When the Prysm team comes back from the holidays break, I'll work with them to tackle this issue.
## Going forward
Next week, I'm planning to implement the `StreamBlocksAltair` API. This is pretty exciting because it's the last endpoint that hasn't been assigned to someone yet, which means that all endpoints have either been merged into the `develop` branch, have a PR opened for them or are actively being worked on by an EPF fellow:
Legend:
|Symbol | State |
|-------------------|-----------------------|
|:x: | Not ready for PR |
|:o: | PR opened |
|:heavy_check_mark: | Merged into `develop` |
| Done | Owner | Endpoint |
|--------------------|----------|-------------------------------------|
| :x: | pavignol | GetDuties |
| :heavy_check_mark: | pavignol | GetBeaconBlock |
| :heavy_check_mark: | pavignol | ProposeBeaconBlock |
| :heavy_check_mark: | pavignol | PrepareBeaconProposer |
| :heavy_check_mark: | pavignol | GetAttestationData |
| :o: | dhruv | ProposeAttestation |
| :x: | dhruv | SubmitAggregateSelectionProof |
| :x: | dhruv | SubmitSignedAggregateSelectionProof |
| :heavy_check_mark: | pavignol | ProposeExit |
| :o: | pavignol | SubscribeCommitteeSubnets |
| :o: | manu | SubmitValidatorRegistrations |
| :heavy_check_mark: | manu | ValidatorIndex |
| :heavy_check_mark: | manu | ValidatorStatus |
| :o: | manu | MultipleValidatorStatus |
| :o: | pavignol | SubmitSignedContributionAndProof |
| :o: | manu | SubmitSyncMessage |
| :x: | dhruv | GetSyncSubcommitteeIndex |
| :x: | dhruv | GetSyncMessageBlockRoot |
| :x: | pavignol | StreamDuties |
| :heavy_check_mark: | pavignol | WaitForChainStart |
| :heavy_check_mark: | manu | WaitForActivation |
| :x: | pavignol | StreamBlocksAltair |
| :heavy_check_mark: | pavignol | DomainData |
| :x: | manu | GetFeeRecipientByPubKey |
| :x: | manu | CheckDoppelGanger |
| :x: | dhruv | GetSyncCommitteeContribution |