prysm-pulse/beacon-chain/rpc/apimiddleware/endpoint_factory.go
Radosław Kapka 57fac9b74f
Improve API Middleware design (#9324)
* remove superfluous WriteHeader call

* move custom handlers outside hooks

* rename OnPostStart hook

* function that returns a default endpoint

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 20:21:43 +00:00

183 lines
8.0 KiB
Go

package apimiddleware
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared/gateway"
)
// BeaconEndpointFactory creates endpoints used for running beacon chain API calls through the API Middleware.
type BeaconEndpointFactory struct {
}
func (f *BeaconEndpointFactory) IsNil() bool {
return f == nil
}
// Paths is a collection of all valid beacon chain API paths.
func (f *BeaconEndpointFactory) Paths() []string {
return []string{
"/eth/v1/beacon/genesis",
"/eth/v1/beacon/states/{state_id}/root",
"/eth/v1/beacon/states/{state_id}/fork",
"/eth/v1/beacon/states/{state_id}/finality_checkpoints",
"/eth/v1/beacon/states/{state_id}/validators",
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}",
"/eth/v1/beacon/states/{state_id}/validator_balances",
"/eth/v1/beacon/states/{state_id}/committees",
"/eth/v1/beacon/headers",
"/eth/v1/beacon/headers/{block_id}",
"/eth/v1/beacon/blocks",
"/eth/v1/beacon/blocks/{block_id}",
"/eth/v1/beacon/blocks/{block_id}/root",
"/eth/v1/beacon/blocks/{block_id}/attestations",
"/eth/v1/beacon/pool/attestations",
"/eth/v1/beacon/pool/attester_slashings",
"/eth/v1/beacon/pool/proposer_slashings",
"/eth/v1/beacon/pool/voluntary_exits",
"/eth/v1/node/identity",
"/eth/v1/node/peers",
"/eth/v1/node/peers/{peer_id}",
"/eth/v1/node/peer_count",
"/eth/v1/node/version",
"/eth/v1/node/syncing",
"/eth/v1/node/health",
"/eth/v1/debug/beacon/states/{state_id}",
"/eth/v1/debug/beacon/heads",
"/eth/v1/config/fork_schedule",
"/eth/v1/config/deposit_contract",
"/eth/v1/config/spec",
"/eth/v1/events",
"/eth/v1/validator/duties/attester/{epoch}",
"/eth/v1/validator/duties/proposer/{epoch}",
"/eth/v1/validator/blocks/{slot}",
"/eth/v1/validator/attestation_data",
"/eth/v1/validator/aggregate_attestation",
"/eth/v1/validator/beacon_committee_subscriptions",
"/eth/v1/validator/aggregate_and_proofs",
}
}
// Create returns a new endpoint for the provided API path.
func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
endpoint := gateway.DefaultEndpoint()
switch path {
case "/eth/v1/beacon/genesis":
endpoint.GetResponse = &genesisResponseJson{}
case "/eth/v1/beacon/states/{state_id}/root":
endpoint.GetResponse = &stateRootResponseJson{}
case "/eth/v1/beacon/states/{state_id}/fork":
endpoint.GetResponse = &stateForkResponseJson{}
case "/eth/v1/beacon/states/{state_id}/finality_checkpoints":
endpoint.GetResponse = &stateFinalityCheckpointResponseJson{}
case "/eth/v1/beacon/states/{state_id}/validators":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "id", Hex: true}, {Name: "status", Enum: true}}
endpoint.GetResponse = &stateValidatorsResponseJson{}
case "/eth/v1/beacon/states/{state_id}/validators/{validator_id}":
endpoint.GetResponse = &stateValidatorResponseJson{}
case "/eth/v1/beacon/states/{state_id}/validator_balances":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "id", Hex: true}}
endpoint.GetResponse = &validatorBalancesResponseJson{}
case "/eth/v1/beacon/states/{state_id}/committees":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "epoch"}, {Name: "index"}, {Name: "slot"}}
endpoint.GetResponse = &stateCommitteesResponseJson{}
case "/eth/v1/beacon/headers":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "parent_root", Hex: true}}
endpoint.GetResponse = &blockHeadersResponseJson{}
case "/eth/v1/beacon/headers/{block_id}":
endpoint.GetResponse = &blockHeaderResponseJson{}
case "/eth/v1/beacon/blocks":
endpoint.PostRequest = &beaconBlockContainerJson{}
endpoint.Hooks = gateway.HookCollection{
OnPostDeserializeRequestBodyIntoContainer: []gateway.Hook{prepareGraffiti},
}
case "/eth/v1/beacon/blocks/{block_id}":
endpoint.GetResponse = &blockResponseJson{}
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconBlockSSZ}
case "/eth/v1/beacon/blocks/{block_id}/root":
endpoint.GetResponse = &blockRootResponseJson{}
case "/eth/v1/beacon/blocks/{block_id}/attestations":
endpoint.GetResponse = &blockAttestationsResponseJson{}
case "/eth/v1/beacon/pool/attestations":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
endpoint.GetResponse = &attestationsPoolResponseJson{}
endpoint.PostRequest = &submitAttestationRequestJson{}
endpoint.Err = &submitAttestationsErrorJson{}
endpoint.Hooks = gateway.HookCollection{
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapAttestationsArray},
}
case "/eth/v1/beacon/pool/attester_slashings":
endpoint.PostRequest = &attesterSlashingJson{}
endpoint.GetResponse = &attesterSlashingsPoolResponseJson{}
case "/eth/v1/beacon/pool/proposer_slashings":
endpoint.PostRequest = &proposerSlashingJson{}
endpoint.GetResponse = &proposerSlashingsPoolResponseJson{}
case "/eth/v1/beacon/pool/voluntary_exits":
endpoint.PostRequest = &signedVoluntaryExitJson{}
endpoint.GetResponse = &voluntaryExitsPoolResponseJson{}
case "/eth/v1/node/identity":
endpoint.GetResponse = &identityResponseJson{}
case "/eth/v1/node/peers":
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "state", Enum: true}, {Name: "direction", Enum: true}}
endpoint.GetResponse = &peersResponseJson{}
case "/eth/v1/node/peers/{peer_id}":
endpoint.RequestURLLiterals = []string{"peer_id"}
endpoint.GetResponse = &peerResponseJson{}
case "/eth/v1/node/peer_count":
endpoint.GetResponse = &peerCountResponseJson{}
case "/eth/v1/node/version":
endpoint.GetResponse = &versionResponseJson{}
case "/eth/v1/node/syncing":
endpoint.GetResponse = &syncingResponseJson{}
case "/eth/v1/node/health":
// Use default endpoint
case "/eth/v1/debug/beacon/states/{state_id}":
endpoint.GetResponse = &beaconStateResponseJson{}
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconStateSSZ}
case "/eth/v1/debug/beacon/heads":
endpoint.GetResponse = &forkChoiceHeadsResponseJson{}
case "/eth/v1/config/fork_schedule":
endpoint.GetResponse = &forkScheduleResponseJson{}
case "/eth/v1/config/deposit_contract":
endpoint.GetResponse = &depositContractResponseJson{}
case "/eth/v1/config/spec":
endpoint.GetResponse = &specResponseJson{}
case "/eth/v1/events":
endpoint.CustomHandlers = []gateway.CustomHandler{handleEvents}
case "/eth/v1/validator/duties/attester/{epoch}":
endpoint.PostRequest = &attesterDutiesRequestJson{}
endpoint.PostResponse = &attesterDutiesResponseJson{}
endpoint.RequestURLLiterals = []string{"epoch"}
endpoint.Hooks = gateway.HookCollection{
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapValidatorIndicesArray},
}
case "/eth/v1/validator/duties/proposer/{epoch}":
endpoint.GetResponse = &proposerDutiesResponseJson{}
endpoint.RequestURLLiterals = []string{"epoch"}
case "/eth/v1/validator/blocks/{slot}":
endpoint.GetResponse = &produceBlockResponseJson{}
endpoint.RequestURLLiterals = []string{"slot"}
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}}
case "/eth/v1/validator/attestation_data":
endpoint.GetResponse = &produceAttestationDataResponseJson{}
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
case "/eth/v1/validator/aggregate_attestation":
endpoint.GetResponse = &aggregateAttestationResponseJson{}
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "attestation_data_root", Hex: true}, {Name: "slot"}}
case "/eth/v1/validator/beacon_committee_subscriptions":
endpoint.PostRequest = &submitAggregateAndProofsRequestJson{}
endpoint.Hooks = gateway.HookCollection{
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapBeaconCommitteeSubscriptionsArray},
}
case "/eth/v1/validator/aggregate_and_proofs":
endpoint.PostRequest = &submitAggregateAndProofsRequestJson{}
endpoint.Hooks = gateway.HookCollection{
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapSignedAggregateAndProofArray},
}
default:
return nil, errors.New("invalid path")
}
endpoint.Path = path
return &endpoint, nil
}