prysm-pulse/validator/client/beacon-api/get_beacon_block.go
terence 5a66807989
Update to V5 (#13622)
* First take at updating everything to v5

* Patch gRPC gateway to use prysm v5

Fix patch

* Update go ssz

---------

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
2024-02-15 05:46:47 +00:00

192 lines
6.6 KiB
Go

package beacon_api
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
neturl "net/url"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/network/httputil"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
)
type abstractProduceBlockResponseJson struct {
Version string `json:"version"`
Data json.RawMessage `json:"data"`
}
func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal []byte, graffiti []byte) (*ethpb.GenericBeaconBlock, error) {
queryParams := neturl.Values{}
queryParams.Add("randao_reveal", hexutil.Encode(randaoReveal))
if len(graffiti) > 0 {
queryParams.Add("graffiti", hexutil.Encode(graffiti))
}
var ver string
var blinded bool
var decoder *json.Decoder
// Try v3 endpoint first. If it's not supported, then we fall back to older endpoints.
// We try the blinded block endpoint first. If it fails, we assume that we got a full block and try the full block endpoint.
queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{}
err := c.jsonRestHandler.Get(ctx, queryUrl, &produceBlockV3ResponseJson)
errJson := &httputil.DefaultJsonError{}
if err != nil {
if !errors.As(err, &errJson) {
return nil, err
}
if errJson.Code != http.StatusNotFound {
return nil, errJson
}
log.Debug("Endpoint /eth/v3/validator/blocks is not supported, falling back to older endpoints for block proposal.")
fallbackResp, err := c.fallBackToBlinded(ctx, slot, queryParams)
errJson = &httputil.DefaultJsonError{}
if err != nil {
if !errors.As(err, &errJson) {
return nil, err
}
log.Debug("Endpoint /eth/v1/validator/blinded_blocks failed to produce a blinded block, trying /eth/v2/validator/blocks.")
fallbackResp, err = c.fallBackToFull(ctx, slot, queryParams)
if err != nil {
return nil, err
}
blinded = false
} else {
blinded = true
}
ver = fallbackResp.Version
decoder = json.NewDecoder(bytes.NewReader(fallbackResp.Data))
} else {
ver = produceBlockV3ResponseJson.Version
blinded = produceBlockV3ResponseJson.ExecutionPayloadBlinded
decoder = json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data))
}
var response *ethpb.GenericBeaconBlock
switch ver {
case version.String(version.Phase0):
jsonPhase0Block := structs.BeaconBlock{}
if err := decoder.Decode(&jsonPhase0Block); err != nil {
return nil, errors.Wrap(err, "failed to decode phase0 block response json")
}
genericBlock, err := jsonPhase0Block.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get phase0 block")
}
response = genericBlock
case version.String(version.Altair):
jsonAltairBlock := structs.BeaconBlockAltair{}
if err := decoder.Decode(&jsonAltairBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode altair block response json")
}
genericBlock, err := jsonAltairBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get altair block")
}
response = genericBlock
case version.String(version.Bellatrix):
if blinded {
jsonBellatrixBlock := structs.BlindedBeaconBlockBellatrix{}
if err := decoder.Decode(&jsonBellatrixBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json")
}
genericBlock, err := jsonBellatrixBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded bellatrix block")
}
response = genericBlock
} else {
jsonBellatrixBlock := structs.BeaconBlockBellatrix{}
if err := decoder.Decode(&jsonBellatrixBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode bellatrix block response json")
}
genericBlock, err := jsonBellatrixBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get bellatrix block")
}
response = genericBlock
}
case version.String(version.Capella):
if blinded {
jsonCapellaBlock := structs.BlindedBeaconBlockCapella{}
if err := decoder.Decode(&jsonCapellaBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded capella block response json")
}
genericBlock, err := jsonCapellaBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded capella block")
}
response = genericBlock
} else {
jsonCapellaBlock := structs.BeaconBlockCapella{}
if err := decoder.Decode(&jsonCapellaBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode capella block response json")
}
genericBlock, err := jsonCapellaBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get capella block")
}
response = genericBlock
}
case version.String(version.Deneb):
if blinded {
jsonDenebBlock := structs.BlindedBeaconBlockDeneb{}
if err := decoder.Decode(&jsonDenebBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded deneb block response json")
}
genericBlock, err := jsonDenebBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded deneb block")
}
response = genericBlock
} else {
jsonDenebBlockContents := structs.BeaconBlockContentsDeneb{}
if err := decoder.Decode(&jsonDenebBlockContents); err != nil {
return nil, errors.Wrap(err, "failed to decode deneb block response json")
}
genericBlock, err := jsonDenebBlockContents.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get deneb block")
}
response = genericBlock
}
default:
return nil, errors.Errorf("unsupported consensus version `%s`", ver)
}
return response, nil
}
func (c beaconApiValidatorClient) fallBackToBlinded(
ctx context.Context,
slot primitives.Slot,
queryParams neturl.Values,
) (*abstractProduceBlockResponseJson, error) {
resp := &abstractProduceBlockResponseJson{}
url := buildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams)
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
return nil, err
}
return resp, nil
}
func (c beaconApiValidatorClient) fallBackToFull(
ctx context.Context,
slot primitives.Slot,
queryParams neturl.Values,
) (*abstractProduceBlockResponseJson, error) {
resp := &abstractProduceBlockResponseJson{}
url := buildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams)
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
return nil, err
}
return resp, nil
}