Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow users to publish blobs #14442

Merged
merged 12 commits into from
Oct 1, 2024
Next Next commit
allow users to publish blobs
Allowing users to publish blobs before publishing blocks, gives the blobs a head start. They can begin to propagate around the network while the block is being validated.
  • Loading branch information
0w3n-d committed Oct 1, 2024
commit 1898ac044cbbd050c93df9198ca835b0934248c6
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- 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

### Changed

Expand Down
1 change: 1 addition & 0 deletions api/server/structs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
srcs = [
"block.go",
"conversions.go",
"conversions_blob.go",
"conversions_block.go",
"conversions_lightclient.go",
"conversions_state.go",
Expand Down
61 changes: 61 additions & 0 deletions api/server/structs/conversions_blob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package structs

import (
"strconv"

"github.com/prysmaticlabs/prysm/v5/api/server"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)

func (sc *Sidecar) ToConsensus() (*eth.BlobSidecar, error) {
if sc == nil {
return nil, errNilValue
}

index, err := strconv.ParseUint(sc.Index, 10, 64)
if err != nil {
return nil, server.NewDecodeError(err, "Index")
}

blob, err := bytesutil.DecodeHexWithLength(sc.Blob, 131072)
if err != nil {
return nil, server.NewDecodeError(err, "Blob")
}

kzgCommitment, err := bytesutil.DecodeHexWithLength(sc.KzgCommitment, 48)
if err != nil {
return nil, server.NewDecodeError(err, "KzgCommitment")
}

kzgProof, err := bytesutil.DecodeHexWithLength(sc.KzgProof, 48)
if err != nil {
return nil, server.NewDecodeError(err, "KzgProof")
}

header, err := sc.SignedBeaconBlockHeader.ToConsensus()
if err != nil {
return nil, server.NewDecodeError(err, "SignedBeaconBlockHeader")
}

// decode the commitment inclusion proof
var commitmentInclusionProof [][]byte
for _, proof := range sc.CommitmentInclusionProof {
proofBytes, err := bytesutil.DecodeHexWithLength(proof, 32)
if err != nil {
return nil, server.NewDecodeError(err, "CommitmentInclusionProof")
}
commitmentInclusionProof = append(commitmentInclusionProof, proofBytes)
}

bsc := &eth.BlobSidecar{
Index: index,
Blob: blob,
KzgCommitment: kzgCommitment,
KzgProof: kzgProof,
SignedBlockHeader: header,
CommitmentInclusionProof: commitmentInclusionProof,
}

return bsc, nil
}
6 changes: 6 additions & 0 deletions api/server/structs/conversions_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
var ErrUnsupportedConversion = errors.New("Could not determine api struct type to use for value")

func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, error) {
if h == nil {
return nil, errNilValue
}
msg, err := h.Message.ToConsensus()
if err != nil {
return nil, server.NewDecodeError(err, "Message")
Expand All @@ -36,6 +39,9 @@ func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, e
}

func (h *BeaconBlockHeader) ToConsensus() (*eth.BeaconBlockHeader, error) {
if h == nil {
return nil, errNilValue
}
s, err := strconv.ParseUint(h.Slot, 10, 64)
if err != nil {
return nil, server.NewDecodeError(err, "Slot")
Expand Down
9 changes: 9 additions & 0 deletions api/server/structs/endpoints_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,12 @@ type Sidecar struct {
KzgProof string `json:"kzg_proof"`
CommitmentInclusionProof []string `json:"kzg_commitment_inclusion_proof"`
}

type BlobSidecars struct {
Sidecars []*Sidecar `json:"sidecars"`
}

type PublishBlobsRequest struct {
BlobSidecars *BlobSidecars `json:"blob_sidecars"`
BlockRoot string `json:"block_root"`
}
12 changes: 12 additions & 0 deletions beacon-chain/rpc/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,8 @@ func (s *Service) prysmBeaconEndpoints(
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
FinalizationFetcher: s.cfg.FinalizationFetcher,
CoreService: coreService,
Broadcaster: s.cfg.Broadcaster,
BlobReceiver: s.cfg.BlobReceiver,
}

const namespace = "prysm.beacon"
Expand Down Expand Up @@ -992,6 +994,16 @@ func (s *Service) prysmBeaconEndpoints(
handler: server.GetChainHead,
methods: []string{http.MethodGet},
},
{
template: "/prysm/v1/beacon/blobs",
name: namespace + ".PublishBlobs",
middleware: []middleware.Middleware{
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
},
handler: server.PublishBlobs,
methods: []string{http.MethodPost},
},
}
}

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 @@ -115,6 +115,7 @@ func Test_endpoints(t *testing.T) {
"/eth/v1/beacon/states/{state_id}/validator_count": {http.MethodGet},
"/prysm/v1/beacon/states/{state_id}/validator_count": {http.MethodGet},
"/prysm/v1/beacon/chain_head": {http.MethodGet},
"/prysm/v1/beacon/blobs": {http.MethodPost},
}

prysmNodeRoutes := map[string][]string{
Expand Down
6 changes: 6 additions & 0 deletions beacon-chain/rpc/prysm/beacon/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/rpc/core:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/eth/shared:go_default_library",
Expand All @@ -22,9 +23,11 @@ go_library(
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/httputil:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
Expand All @@ -47,13 +50,16 @@ go_test(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
"//beacon-chain/p2p/testing:go_default_library",
"//beacon-chain/rpc/core:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/testing:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/stategen/mock:go_default_library",
"//beacon-chain/sync/initial-sync/testing:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
Expand Down
51 changes: 51 additions & 0 deletions beacon-chain/rpc/prysm/beacon/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
"github.com/prysmaticlabs/prysm/v5/network/httputil"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
Expand Down Expand Up @@ -183,3 +185,52 @@ func (s *Server) GetChainHead(w http.ResponseWriter, r *http.Request) {
}
httputil.WriteJson(w, response)
}

func (s *Server) PublishBlobs(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlobs")
defer span.End()
if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) {
return
}

var req structs.PublishBlobsRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
httputil.HandleError(w, "Could not decode JSON request body", http.StatusBadRequest)
return
}
if req.BlobSidecars == nil {
httputil.HandleError(w, "Missing blob sidecars", http.StatusBadRequest)
return
}

root, err := bytesutil.DecodeHexWithLength(req.BlockRoot, 32)
if err != nil {
httputil.HandleError(w, "Could not decode block root", http.StatusBadRequest)
rkapka marked this conversation as resolved.
Show resolved Hide resolved
return
}

for _, blobSidecar := range req.BlobSidecars.Sidecars {
prestonvanloon marked this conversation as resolved.
Show resolved Hide resolved
sc, err := blobSidecar.ToConsensus()
if err != nil {
httputil.HandleError(w, "Could not decode blob sidecar", http.StatusBadRequest)
rkapka marked this conversation as resolved.
Show resolved Hide resolved
return
}

readOnlySc, err := blocks.NewROBlobWithRoot(sc, bytesutil.ToBytes32(root))
if err != nil {
httputil.HandleError(w, "Could not create read-only blob", http.StatusInternalServerError)
rkapka marked this conversation as resolved.
Show resolved Hide resolved
return
}

verifiedBlob := blocks.NewVerifiedROBlob(readOnlySc)
if err := s.BlobReceiver.ReceiveBlob(ctx, verifiedBlob); err != nil {
httputil.HandleError(w, "Could not receive blob", http.StatusInternalServerError)
rkapka marked this conversation as resolved.
Show resolved Hide resolved
return
}

if err := s.Broadcaster.BroadcastBlob(ctx, sc.Index, sc); err != nil {
httputil.HandleError(w, "Failed to broadcast blob", http.StatusInternalServerError)
rkapka marked this conversation as resolved.
Show resolved Hide resolved
return
}
}
}
Loading