Auditing Beacon APIs - notes for implementers

The purpose of this document is to provide guidelines for developers attempting to improve the existing Beacon API endpoints. The assumption is that you will be rewriting the existing gRPC endpoint into a new HTTP handler.

Prioritize endpoints which are consumed by the validator client

This project's main aim is to get Prysm closer to run a validator+node combination communicating through Beacon APIs. Not all Beacon API endpoints specified are used by the validator client throught its lifetime. You can find all relevant endpoints by navigating through files in https://github.com/prysmaticlabs/prysm/tree/develop/validator/client/beacon-api. For example, we can see the following code in attestation_data.go:

query := buildURL("/eth/v1/validator/attestation_data", params)
produceAttestationDataResponseJson := rpcmiddleware.ProduceAttestationDataResponseJson{}

if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, query, &produceAttestationDataResponseJson); err != nil {
    return nil, errors.Wrap(err, "failed to get json response")
}

In this code snipped we call /eth/v1/validator/attestation_data. To find out more information about this endpoint, we go to proto/eth/service/validator_service.go:

// Spec: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.3.0#/Validator/produceAttestationData
rpc ProduceAttestationData(v1.ProduceAttestationDataRequest) returns (v1.ProduceAttestationDataResponse) {
    option (google.api.http) = { get: "/internal/eth/v1/validator/attestation_data" };
}

Here is a full list of endpoints used by the validator client:

  • /eth/v1/validator/attestation_data
  • /eth/v1/beacon/headers/{block_id}
  • /eth/v1/beacon/states/{state_id}/finality_checkpoints
  • /eth/v1/beacon/states/{state_id}/fork
  • /eth/v1/beacon/headers
  • /eth/v1/validator/liveness
  • /eth/v1/node/syncing
  • /eth/v1/config/deposit_contract
  • /eth/v1/beacon/states/{state_id}/committees
  • /eth/v1/validator/duties/attester/{epoch}
  • /eth/v1/validator/duties/proposer/{epoch}
  • /eth/v1/validator/duties/sync/{epoch}
  • /eth/v1/beacon/genesis
  • /eth/v1/validator/prepare_beacon_proposer
  • /eth/v1/beacon/pool/attestations
  • /eth/v1/beacon/blinded_blocks
  • /eth/v1/beacon/blocks
  • /eth/v1/beacon/pool/voluntary_exits
  • /eth/v1/validator/register_validator
  • /eth/v1/beacon/states/{state_id}/validators
  • /eth/v1/validator/aggregate_attestation
  • /eth/v1/validator/aggregate_and_proofs
  • /eth/v1/validator/contribution_and_proofs
  • /eth/v1/validator/beacon_committee_subscriptions
  • /eth/v1/beacon/pool/sync_committees
  • /eth/v1/beacon/blocks/{block_id}/root
  • /eth/v1/validator/sync_committee_contribution

Reuse code from beacon-chain/prysm/v1alpha1

RPC endpoints defined in the v1alpha1 directory are currently being used by the validator client. This means the code is reasonably fast and has been battle-tested for several years. Therefore it doesn't make much sense to reinvent the wheel when an identical functionality already exists for v1alpha. In such case you should extract the logic from v1alpha to a separate package and use it both in v1alpha and in the new HTTP handler. See https://github.com/prysmaticlabs/prysm/pull/12557 for an example.

In cases where the functionality exists only for Beacon API, we won't need the gRPC version once we have the HTTP one. Therefore the code can be moved over and the old handler can be removed. See https://github.com/prysmaticlabs/prysm/pull/12643 for an example.

Provide benchmarks

We want our Beacon API endpoints to be of production quality, meaning they can handle requests in a timely manner. Provide benchmarks that show the roundtrip time of a request, ideally for several scenarios (e.g. fetching state by root/slot in case of a state param, or sending different data in the body of a POST request). Pull requests without benchmarks will not be approved.

Run end-to-end tests

There is an end-to-end test case during which the validator client uses Beacon API to talk to the beacon node. To run the test, invoke the following command:

bazel test //testing/endtoend:go_minimal_scenario_test --test_filter=TestEndToEnd_MinimalConfig_ValidatorRESTApi --test_env=E2E_EPOCHS=10 --test_timeout=10000 --test_output=streamed

Test your code with https://github.com/rauljordan/beacon-api-checker

To have better confidence that endpoints return correct results, you should cross-compare them with another consensus client, such as Lighthouse. One of our developers created a tool that does just that, so please test your implementation with it before submitting a pull request.

Select a repo