Skip to content

Commit

Permalink
Beacon API handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
rkapka committed Nov 3, 2024
1 parent aeb34bd commit e4cdfe4
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 88 deletions.
1 change: 1 addition & 0 deletions beacon-chain/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,7 @@ func (b *BeaconNode) registerRPCService(router *http.ServeMux) error {
BlobStorage: b.BlobStorage,
TrackedValidatorsCache: b.trackedValidatorsCache,
PayloadIDCache: b.payloadIDCache,
LCStore: b.lcStore,
})

return b.services.RegisterService(rpcService)
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/rpc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/filesystem:go_default_library",
"//beacon-chain/execution:go_default_library",
"//beacon-chain/light-client:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/rpc/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta
HeadFetcher: s.cfg.HeadFetcher,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
BeaconDB: s.cfg.BeaconDB,
LCStore: s.cfg.LCStore,
}

const namespace = "lightclient"
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/rpc/eth/light-client/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_library(
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/light-client:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/light-client:go_default_library",
"//beacon-chain/rpc/eth/shared:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state:go_default_library",
Expand Down
159 changes: 71 additions & 88 deletions beacon-chain/rpc/eth/light-client/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package lightclient
import (
"context"
"fmt"
"math"
"net/http"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/api"
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
Expand Down Expand Up @@ -45,18 +45,33 @@ func (s *Server) GetLightClientBootstrap(w http.ResponseWriter, req *http.Reques
return
}

bootstrap, err := newLightClientBootstrapFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), state, blk)
bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), state, blk)
if err != nil {
httputil.HandleError(w, "could not get light client bootstrap: "+err.Error(), http.StatusInternalServerError)
return
}
response := &structs.LightClientBootstrapResponse{
Version: version.String(blk.Version()),
Data: bootstrap,
}
w.Header().Set(api.VersionHeader, version.String(version.Deneb))

httputil.WriteJson(w, response)
w.Header().Set(api.VersionHeader, version.String(bootstrap.Version()))

if httputil.RespondWithSsz(req) {
ssz, err := bootstrap.MarshalSSZ()
if err != nil {
httputil.HandleError(w, "could not marshal bootstrap to SSZ: "+err.Error(), http.StatusInternalServerError)
return
}
httputil.WriteSsz(w, ssz, "light_client_bootstrap.ssz")
} else {
data, err := structs.LightClientBootsrapFromConsensus(bootstrap)
if err != nil {
httputil.HandleError(w, "could not marshal bootstrap to JSON: "+err.Error(), http.StatusInternalServerError)
return
}
response := &structs.LightClientBootstrapResponse{
Version: version.String(bootstrap.Version()),
Data: data,
}
httputil.WriteJson(w, response)
}
}

// GetLightClientUpdatesByRange - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/updates.yaml
Expand Down Expand Up @@ -137,6 +152,7 @@ func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.R
return
}

// TODO: we shouldn't append response objects in a loop
updateResponse := &structs.LightClientUpdateResponse{
Version: version.String(update.Version()),
Data: updateJson,
Expand All @@ -150,105 +166,72 @@ func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.R

// GetLightClientFinalityUpdate - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/finality_update.yaml
func (s *Server) GetLightClientFinalityUpdate(w http.ResponseWriter, req *http.Request) {
ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientFinalityUpdate")
_, span := trace.StartSpan(req.Context(), "beacon.GetLightClientFinalityUpdate")
defer span.End()

// Finality update needs super majority of sync committee signatures
minSyncCommitteeParticipants := float64(params.BeaconConfig().MinSyncCommitteeParticipants)
minSignatures := uint64(math.Ceil(minSyncCommitteeParticipants * 2 / 3))
update := s.LCStore.LastLCFinalityUpdate

block, err := s.suitableBlock(ctx, minSignatures)
if !shared.WriteBlockFetchError(w, block, err) {
if update == nil {
httputil.HandleError(w, "No light client finality update available", http.StatusNotFound)
return
}

st, err := s.Stater.StateBySlot(ctx, block.Block().Slot())
if err != nil {
httputil.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set(api.VersionHeader, version.String(update.Version()))

attestedRoot := block.Block().ParentRoot()
attestedBlock, err := s.Blocker.Block(ctx, attestedRoot[:])
if !shared.WriteBlockFetchError(w, block, errors.Wrap(err, "could not get attested block")) {
return
}
attestedSlot := attestedBlock.Block().Slot()
attestedState, err := s.Stater.StateBySlot(ctx, attestedSlot)
if err != nil {
httputil.HandleError(w, "Could not get attested state: "+err.Error(), http.StatusInternalServerError)
return
}

var finalizedBlock interfaces.ReadOnlySignedBeaconBlock
finalizedCheckpoint := attestedState.FinalizedCheckpoint()
if finalizedCheckpoint == nil {
httputil.HandleError(w, "Attested state does not have a finalized checkpoint", http.StatusInternalServerError)
return
}
finalizedRoot := bytesutil.ToBytes32(finalizedCheckpoint.Root)
finalizedBlock, err = s.Blocker.Block(ctx, finalizedRoot[:])
if !shared.WriteBlockFetchError(w, block, errors.Wrap(err, "could not get finalized block")) {
return
}

update, err := newLightClientFinalityUpdateFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), st, block, attestedState, attestedBlock, finalizedBlock)
if err != nil {
httputil.HandleError(w, "Could not get light client finality update: "+err.Error(), http.StatusInternalServerError)
return
}

response := &structs.LightClientFinalityUpdateResponse{
Version: version.String(attestedState.Version()),
Data: update,
if httputil.RespondWithSsz(req) {
ssz, err := update.MarshalSSZ()
if err != nil {
httputil.HandleError(w, "could not marshal update to SSZ: "+err.Error(), http.StatusInternalServerError)
return
}
httputil.WriteSsz(w, ssz, "light_client_finality_update.ssz")
} else {
data, err := structs.LightClientFinalityUpdateFromConsensus(update)
if err != nil {
httputil.HandleError(w, "could not marshal update to JSON: "+err.Error(), http.StatusInternalServerError)
return
}
response := &structs.LightClientFinalityUpdateResponse{
Version: version.String(update.Version()),
Data: data,
}
httputil.WriteJson(w, response)
}

httputil.WriteJson(w, response)
}

// GetLightClientOptimisticUpdate - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/optimistic_update.yaml
func (s *Server) GetLightClientOptimisticUpdate(w http.ResponseWriter, req *http.Request) {
ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientOptimisticUpdate")
_, span := trace.StartSpan(req.Context(), "beacon.GetLightClientOptimisticUpdate")
defer span.End()

block, err := s.suitableBlock(ctx, params.BeaconConfig().MinSyncCommitteeParticipants)
if !shared.WriteBlockFetchError(w, block, err) {
return
}
st, err := s.Stater.StateBySlot(ctx, block.Block().Slot())
if err != nil {
httputil.HandleError(w, "could not get state: "+err.Error(), http.StatusInternalServerError)
return
}
attestedRoot := block.Block().ParentRoot()
attestedBlock, err := s.Blocker.Block(ctx, attestedRoot[:])
if err != nil {
httputil.HandleError(w, "Could not get attested block: "+err.Error(), http.StatusInternalServerError)
return
}
if attestedBlock == nil {
httputil.HandleError(w, "Attested block is nil", http.StatusInternalServerError)
return
}
attestedSlot := attestedBlock.Block().Slot()
attestedState, err := s.Stater.StateBySlot(ctx, attestedSlot)
if err != nil {
httputil.HandleError(w, "Could not get attested state: "+err.Error(), http.StatusInternalServerError)
return
}
update := s.LCStore.LastLCOptimisticUpdate

update, err := newLightClientOptimisticUpdateFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), st, block, attestedState, attestedBlock)
if err != nil {
httputil.HandleError(w, "Could not get light client optimistic update: "+err.Error(), http.StatusInternalServerError)
if update == nil {
httputil.HandleError(w, "No light client optimistic update available", http.StatusNotFound)
return
}

response := &structs.LightClientOptimisticUpdateResponse{
Version: version.String(attestedState.Version()),
Data: update,
}
w.Header().Set(api.VersionHeader, version.String(update.Version()))

httputil.WriteJson(w, response)
if httputil.RespondWithSsz(req) {
ssz, err := update.MarshalSSZ()
if err != nil {
httputil.HandleError(w, "could not marshal update to SSZ: "+err.Error(), http.StatusInternalServerError)
return
}
httputil.WriteSsz(w, ssz, "light_client_optimistic_update.ssz")
} else {
data, err := structs.LightClientOptimisticUpdateFromConsensus(update)
if err != nil {
httputil.HandleError(w, "could not marshal update to JSON: "+err.Error(), http.StatusInternalServerError)
return
}
response := &structs.LightClientOptimisticUpdateResponse{
Version: version.String(update.Version()),
Data: data,
}
httputil.WriteJson(w, response)
}
}

// suitableBlock returns the latest block that satisfies all criteria required for creating a new update
Expand Down
2 changes: 2 additions & 0 deletions beacon-chain/rpc/eth/light-client/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package lightclient
import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db"
light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup"
)

Expand All @@ -12,4 +13,5 @@ type Server struct {
HeadFetcher blockchain.HeadFetcher
ChainInfoFetcher blockchain.ChainInfoFetcher
BeaconDB db.HeadAccessDatabase
LCStore *light_client.Store
}
2 changes: 2 additions & 0 deletions beacon-chain/rpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/light-client"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/blstoexec"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/slashings"
Expand Down Expand Up @@ -140,6 +141,7 @@ type Config struct {
BlobStorage *filesystem.BlobStorage
TrackedValidatorsCache *cache.TrackedValidatorsCache
PayloadIDCache *cache.PayloadIDCache
LCStore *light_client.Store
}

// NewService instantiates a new RPC service instance that will
Expand Down

0 comments on commit e4cdfe4

Please sign in to comment.