From eda3e434a0679972694bb1102d804bdb28eeadc3 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Tue, 30 Apr 2024 14:10:26 -0500 Subject: [PATCH] refactor ssz api resp handlers to avoid typed pbs --- beacon-chain/rpc/eth/beacon/BUILD.bazel | 1 + beacon-chain/rpc/eth/beacon/handlers.go | 324 ++++-------------------- 2 files changed, 47 insertions(+), 278 deletions(-) diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index 11ded5c96335..d9a8037e3e71 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -59,6 +59,7 @@ go_library( "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_opencensus_go//trace:go_default_library", ], diff --git a/beacon-chain/rpc/eth/beacon/handlers.go b/beacon-chain/rpc/eth/beacon/handlers.go index 03567b8be205..ee8a2698888c 100644 --- a/beacon-chain/rpc/eth/beacon/handlers.go +++ b/beacon-chain/rpc/eth/beacon/handlers.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gorilla/mux" "github.com/pkg/errors" + ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache/depositsnapshot" @@ -46,6 +47,7 @@ const ( var ( errNilBlock = errors.New("nil block") errEquivocatedBlock = errors.New("block is equivocated") + errMarshalSSZ = errors.New("could not marshal block into SSZ") ) type handled bool @@ -117,37 +119,28 @@ func (s *Server) getBlockV2(ctx context.Context, w http.ResponseWriter, blk inte // getBlockSSZV2 returns the SSZ-serialized version of the beacon block for given block ID. func (s *Server) getBlockSSZV2(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) ([]byte, error), ver string) handled { - result, err := get(ctx, blk) - if result != nil { - w.Header().Set(api.VersionHeader, ver) - httputil.WriteSsz(w, result, "beacon_block.ssz") - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true - } - return false - } - - if getBlockHandler(s.getBlockDenebSSZ, version.String(version.Deneb)) { - return - } - if getBlockHandler(s.getBlockCapellaSSZ, version.String(version.Capella)) { - return + result, err := s.getUnblindedBlockRespSSZ(ctx, blk) + if err != nil { + httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) } - if getBlockHandler(s.getBlockBellatrixSSZ, version.String(version.Bellatrix)) { - return + if result == nil { + httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) } - if getBlockHandler(s.getBlockAltairSSZ, version.String(version.Altair)) { - return + w.Header().Set(api.VersionHeader, version.String(blk.Version())) + httputil.WriteSsz(w, result, "beacon_block.ssz") +} + +// getBlindedBlockSSZ returns the SSZ-serialized version of the blinded beacon block for given block id. +func (s *Server) getBlindedBlockSSZ(w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { + result, err := s.getBlindedBlockRespSSZ(blk) + if err != nil { + httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) } - if getBlockHandler(s.getBlockPhase0SSZ, version.String(version.Phase0)) { - return + if result == nil { + httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) + w.Header().Set(api.VersionHeader, version.String(blk.Version())) + httputil.WriteSsz(w, result, "beacon_block.ssz") } // GetBlindedBlock retrieves blinded block for given block id. @@ -166,7 +159,7 @@ func (s *Server) GetBlindedBlock(w http.ResponseWriter, r *http.Request) { } if httputil.RespondWithSsz(r) { - s.getBlindedBlockSSZ(ctx, w, blk) + s.getBlindedBlockSSZ(w, blk) } else { s.getBlindedBlock(ctx, w, blk) } @@ -215,41 +208,6 @@ func (s *Server) getBlindedBlock(ctx context.Context, w http.ResponseWriter, blk httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) } -// getBlindedBlockSSZ returns the SSZ-serialized version of the blinded beacon block for given block id. -func (s *Server) getBlindedBlockSSZ(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) ([]byte, error), ver string) handled { - result, err := get(ctx, blk) - if result != nil { - w.Header().Set(api.VersionHeader, ver) - httputil.WriteSsz(w, result, "beacon_block.ssz") - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true - } - return false - } - - if getBlockHandler(s.getBlockPhase0SSZ, version.String(version.Phase0)) { - return - } - if getBlockHandler(s.getBlockAltairSSZ, version.String(version.Altair)) { - return - } - if getBlockHandler(s.getBlindedBlockBellatrixSSZ, version.String(version.Bellatrix)) { - return - } - if getBlockHandler(s.getBlindedBlockCapellaSSZ, version.String(version.Capella)) { - return - } - if getBlockHandler(s.getBlindedBlockDenebSSZ, version.String(version.Deneb)) { - return - } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) -} - func (*Server) getBlockPhase0(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { consensusBlk, err := blk.PbPhase0Block() if err != nil { @@ -458,135 +416,50 @@ func (s *Server) getBlockDeneb(ctx context.Context, blk interfaces.ReadOnlySigne }, nil } -func (*Server) getBlockPhase0SSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbPhase0Block() +// getUnblindedBlockRespSSZ attempts to reconstruct the full block before calling getBlockRespSSZ to finish the job. +func (s *Server) getUnblindedBlockRespSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { + err := blocks.BeaconBlockIsNil(blk) if err != nil { - return nil, err - } - if consensusBlk == nil { return nil, errNilBlock } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") + if blk.Version() >= version.Bellatrix && blk.IsBlinded() { + blk, err = s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) + if err != nil { + return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") + } } - return sszData, nil + return s.getBlockRespSSZ(blk) } -func (*Server) getBlockAltairSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbAltairBlock() +// getUnblindedBlockRespSSZ attempts to reconstruct the full block before calling getBlockRespSSZ to finish the job. +func (s *Server) getBlindedBlockRespSSZ(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { + err := blocks.BeaconBlockIsNil(blk) if err != nil { - return nil, err - } - if consensusBlk == nil { return nil, errNilBlock } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (s *Server) getBlockBellatrixSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err + if blk.Version() >= version.Bellatrix && !blk.IsBlinded() { + blk, err = blk.ToBlinded() + if err != nil { + return nil, errors.Wrapf(err, "could not convert block to blinded block") } } - - if consensusBlk == nil { - return nil, errNilBlock - } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil + return s.getBlockRespSSZ(blk) } -func (s *Server) getBlockCapellaSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbCapellaBlock() +func (s *Server) getBlockRespSSZ(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { + err := blocks.BeaconBlockIsNil(blk) if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { return nil, errNilBlock } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (s *Server) getBlockDenebSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbDenebBlock() + pb, err := blk.Proto() if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } + return nil, err } - - if consensusBlk == nil { - return nil, errNilBlock + marshaler, ok := pb.(ssz.Marshaler) + if !ok { + return nil, errMarshalSSZ } - sszData, err := consensusBlk.MarshalSSZ() + sszData, err := marshaler.MarshalSSZ() if err != nil { return nil, errors.Wrapf(err, "could not marshal block into SSZ") } @@ -755,111 +628,6 @@ func (s *Server) getBlindedBlockDeneb(ctx context.Context, blk interfaces.ReadOn }, nil } -func (*Server) getBlindedBlockBellatrixSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (*Server) getBlindedBlockCapellaSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbCapellaBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (*Server) getBlindedBlockDenebSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbDenebBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - // GetBlockAttestations retrieves attestation included in requested block. func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestations")