Skip to content

Commit

Permalink
Add /eth/v2/beacon/blocks/{block_id}/attestations (#14478)
Browse files Browse the repository at this point in the history
* add endpoint

* changelog

* fix response

* improvement

* fix test

* James' review

* fix test

* fix version check

* add test for non electra V2

* Review items

* James' review

* Radek' review

* Update CHANGELOG.md

---------

Co-authored-by: Radosław Kapka <[email protected]>
  • Loading branch information
saolyn and rkapka authored Oct 10, 2024
1 parent 2c981d5 commit 57cc495
Show file tree
Hide file tree
Showing 6 changed files with 391 additions and 127 deletions.
14 changes: 7 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- Light client support: Implement `BlockToLightClientHeader` function.
- Light client support: Consensus types.
- GetBeaconStateV2: add Electra case.
- Implement [consensus-specs/3875](https://github.com/ethereum/consensus-specs/pull/3875)
- Tests to ensure sepolia config matches the official upstream yaml
- HTTP endpoint for PublishBlobs
- Implement [consensus-specs/3875](https://github.com/ethereum/consensus-specs/pull/3875).
- Tests to ensure sepolia config matches the official upstream yaml.
- HTTP endpoint for PublishBlobs.
- GetBlockV2, GetBlindedBlock, ProduceBlockV2, ProduceBlockV3: add Electra case.
- Add Electra support and tests for light client functions
- Add Electra support and tests for light client functions.
- fastssz version bump (better error messages).
- SSE implementation that sheds stuck clients. [pr](https://github.com/prysmaticlabs/prysm/pull/14413)
- Add Bellatrix tests for light client functions
- Add Discovery Rebooter Feature

- Add Bellatrix tests for light client functions.
- Add Discovery Rebooter Feature.
- Added GetBlockAttestationsV2 endpoint.

### Changed

Expand Down
7 changes: 7 additions & 0 deletions api/server/structs/endpoints_beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ type GetBlockAttestationsResponse struct {
Data []*Attestation `json:"data"`
}

type GetBlockAttestationsV2Response struct {
Version string `json:"version"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
Data json.RawMessage `json:"data"` // Accepts both `Attestation` and `AttestationElectra` types
}

type GetStateRootResponse struct {
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
Expand Down
9 changes: 9 additions & 0 deletions beacon-chain/rpc/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,15 @@ func (s *Service) beaconEndpoints(
handler: server.GetBlockAttestations,
methods: []string{http.MethodGet},
},
{
template: "/eth/v2/beacon/blocks/{block_id}/attestations",
name: namespace + ".GetBlockAttestationsV2",
middleware: []middleware.Middleware{
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
},
handler: server.GetBlockAttestations,
methods: []string{http.MethodGet},
},
{
template: "/eth/v1/beacon/blinded_blocks/{block_id}",
name: namespace + ".GetBlindedBlock",
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/rpc/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func Test_endpoints(t *testing.T) {
"/eth/v2/beacon/blocks/{block_id}": {http.MethodGet},
"/eth/v1/beacon/blocks/{block_id}/root": {http.MethodGet},
"/eth/v1/beacon/blocks/{block_id}/attestations": {http.MethodGet},
"/eth/v2/beacon/blocks/{block_id}/attestations": {http.MethodGet},
"/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet},
"/eth/v1/beacon/deposit_snapshot": {http.MethodGet},
"/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet},
Expand Down
88 changes: 72 additions & 16 deletions beacon-chain/rpc/eth/beacon/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,10 @@ func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestations")
defer span.End()

blockId := r.PathValue("block_id")
if blockId == "" {
httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest)
return
}
blk, err := s.Blocker.Block(ctx, []byte(blockId))
if !shared.WriteBlockFetchError(w, blk, err) {
blk, isOptimistic, root := s.blockData(ctx, w, r)
if blk == nil {
return
}

consensusAtts := blk.Block().Body().Attestations()
atts := make([]*structs.Attestation, len(consensusAtts))
for i, att := range consensusAtts {
Expand All @@ -221,25 +215,87 @@ func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) {
return
}
}
root, err := blk.Block().HashTreeRoot()
if err != nil {
httputil.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError)
resp := &structs.GetBlockAttestationsResponse{
Data: atts,
ExecutionOptimistic: isOptimistic,
Finalized: s.FinalizationFetcher.IsFinalized(ctx, root),
}
httputil.WriteJson(w, resp)
}

// GetBlockAttestationsV2 retrieves attestation included in requested block.
func (s *Server) GetBlockAttestationsV2(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestationsV2")
defer span.End()

blk, isOptimistic, root := s.blockData(ctx, w, r)
if blk == nil {
return
}
isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
consensusAtts := blk.Block().Body().Attestations()

v := blk.Block().Version()
var attStructs []interface{}
if v >= version.Electra {
for _, att := range consensusAtts {
a, ok := att.(*eth.AttestationElectra)
if !ok {
httputil.HandleError(w, fmt.Sprintf("unable to convert consensus attestations electra of type %T", att), http.StatusInternalServerError)
return
}
attStruct := structs.AttElectraFromConsensus(a)
attStructs = append(attStructs, attStruct)
}
} else {
for _, att := range consensusAtts {
a, ok := att.(*eth.Attestation)
if !ok {
httputil.HandleError(w, fmt.Sprintf("unable to convert consensus attestation of type %T", att), http.StatusInternalServerError)
return
}
attStruct := structs.AttFromConsensus(a)
attStructs = append(attStructs, attStruct)
}
}

attBytes, err := json.Marshal(attStructs)
if err != nil {
httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError)
httputil.HandleError(w, fmt.Sprintf("failed to marshal attestations: %v", err), http.StatusInternalServerError)
return
}

resp := &structs.GetBlockAttestationsResponse{
Data: atts,
resp := &structs.GetBlockAttestationsV2Response{
Version: version.String(v),
ExecutionOptimistic: isOptimistic,
Finalized: s.FinalizationFetcher.IsFinalized(ctx, root),
Data: attBytes,
}
httputil.WriteJson(w, resp)
}

func (s *Server) blockData(ctx context.Context, w http.ResponseWriter, r *http.Request) (interfaces.ReadOnlySignedBeaconBlock, bool, [32]byte) {
blockId := r.PathValue("block_id")
if blockId == "" {
httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest)
return nil, false, [32]byte{}
}
blk, err := s.Blocker.Block(ctx, []byte(blockId))
if !shared.WriteBlockFetchError(w, blk, err) {
return nil, false, [32]byte{}
}

root, err := blk.Block().HashTreeRoot()
if err != nil {
httputil.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError)
return nil, false, [32]byte{}
}
isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
if err != nil {
httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError)
return nil, false, [32]byte{}
}
return blk, isOptimistic, root
}

// PublishBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
// and publish a SignedBeaconBlock by swapping out the transactions_root for the corresponding full list of `transactions`.
// The beacon node should broadcast a newly constructed SignedBeaconBlock to the beacon network, to be included in the
Expand Down
Loading

0 comments on commit 57cc495

Please sign in to comment.