Skip to content

Commit ff72fff

Browse files
authored
feat: fetch blobs via /eth/v1/beacon/blobs from beacon node (#1244)
* feat: featch blobs via /eth/v1/beacon/blobs from beacon node * fix * fix query parameter syntax * bump version
1 parent 9cfdf86 commit ff72fff

File tree

3 files changed

+40
-50
lines changed

3 files changed

+40
-50
lines changed

params/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 9 // Minor version component of the current release
27-
VersionPatch = 9 // Patch version component of the current release
27+
VersionPatch = 10 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

rollup/da_syncer/blob_client/beacon_node_client.go

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package blob_client
22

33
import (
44
"context"
5-
"crypto/sha256"
65
"encoding/json"
76
"fmt"
87
"io"
@@ -29,7 +28,7 @@ type BeaconNodeClient struct {
2928
var (
3029
beaconNodeGenesisEndpoint = "/eth/v1/beacon/genesis"
3130
beaconNodeSpecEndpoint = "/eth/v1/config/spec"
32-
beaconNodeBlobEndpoint = "/eth/v1/beacon/blob_sidecars"
31+
beaconNodeBlobEndpoint = "/eth/v1/beacon/blobs"
3332
)
3433

3534
func NewBeaconNodeClient(apiEndpoint string) (*BeaconNodeClient, error) {
@@ -106,15 +105,31 @@ func NewBeaconNodeClient(apiEndpoint string) (*BeaconNodeClient, error) {
106105
}, nil
107106
}
108107

108+
func (c *BeaconNodeClient) getBlobsPath(slot uint64, versionedHash common.Hash) (string, error) {
109+
basePath, err := url.JoinPath(c.apiEndpoint, beaconNodeBlobEndpoint, fmt.Sprintf("%d", slot))
110+
if err != nil {
111+
return "", fmt.Errorf("failed to join path, err: %w", err)
112+
}
113+
u, err := url.Parse(basePath)
114+
if err != nil {
115+
return "", fmt.Errorf("failed to parse path, err: %w", err)
116+
}
117+
q := u.Query()
118+
q.Set("versioned_hashes", versionedHash.Hex())
119+
u.RawQuery = q.Encode()
120+
queryPath := u.String()
121+
return queryPath, nil
122+
}
123+
109124
func (c *BeaconNodeClient) GetBlobByVersionedHashAndBlockTime(ctx context.Context, versionedHash common.Hash, blockTime uint64) (*kzg4844.Blob, error) {
110125
slot := (blockTime - c.genesisTime) / c.secondsPerSlot
111126

112-
// get blob sidecar for slot
113-
blobSidecarPath, err := url.JoinPath(c.apiEndpoint, beaconNodeBlobEndpoint, fmt.Sprintf("%d", slot))
127+
// get blob by slot and versioned hash
128+
getBlobsPath, err := c.getBlobsPath(slot, versionedHash)
114129
if err != nil {
115-
return nil, fmt.Errorf("failed to join path, err: %w", err)
130+
return nil, fmt.Errorf("failed to create getBlobs path, err: %w", err)
116131
}
117-
req, err := http.NewRequestWithContext(ctx, "GET", blobSidecarPath, nil)
132+
req, err := http.NewRequestWithContext(ctx, "GET", getBlobsPath, nil)
118133
if err != nil {
119134
return nil, fmt.Errorf("failed to create request, err: %w", err)
120135
}
@@ -133,35 +148,27 @@ func (c *BeaconNodeClient) GetBlobByVersionedHashAndBlockTime(ctx context.Contex
133148
return nil, fmt.Errorf("beacon node request failed, status: %s, body: %s", resp.Status, bodyStr)
134149
}
135150

136-
var blobSidecarResp BlobSidecarResp
137-
err = json.NewDecoder(resp.Body).Decode(&blobSidecarResp)
151+
var blobsResp BlobsResp
152+
err = json.NewDecoder(resp.Body).Decode(&blobsResp)
138153
if err != nil {
139154
return nil, fmt.Errorf("failed to decode result into struct, err: %w", err)
140155
}
141156

142-
// find blob with desired versionedHash
143-
for _, blob := range blobSidecarResp.Data {
144-
// calculate blob hash from commitment and check it with desired
145-
commitmentBytes := common.FromHex(blob.KzgCommitment)
146-
if len(commitmentBytes) != lenKZGCommitment {
147-
return nil, fmt.Errorf("len of kzg commitment is not correct, expected: %d, got: %d", lenKZGCommitment, len(commitmentBytes))
148-
}
149-
commitment := kzg4844.Commitment(commitmentBytes)
150-
blobVersionedHash := kzg4844.CalcBlobHashV1(sha256.New(), &commitment)
151-
152-
if blobVersionedHash == versionedHash {
153-
// found desired blob
154-
blobBytes := common.FromHex(blob.Blob)
155-
if len(blobBytes) != lenBlobBytes {
156-
return nil, fmt.Errorf("len of blob data is not correct, expected: %d, got: %d", lenBlobBytes, len(blobBytes))
157-
}
158-
159-
b := kzg4844.Blob(blobBytes)
160-
return &b, nil
161-
}
157+
// sanity check response length
158+
if len(blobsResp.Data) == 0 {
159+
return nil, fmt.Errorf("missing blob %v in slot %d", versionedHash, slot)
160+
}
161+
if len(blobsResp.Data) > 1 {
162+
return nil, fmt.Errorf("more than 1 blob returned from beacon node for slot %d, requested blob hash: %s, expected 1, got: %d", slot, versionedHash.Hex(), len(blobsResp.Data))
162163
}
163164

164-
return nil, fmt.Errorf("missing blob %v in slot %d", versionedHash, slot)
165+
blobBytes := common.FromHex(blobsResp.Data[0])
166+
if len(blobBytes) != lenBlobBytes {
167+
return nil, fmt.Errorf("len of blob data is not correct, expected: %d, got: %d", lenBlobBytes, len(blobBytes))
168+
}
169+
170+
b := kzg4844.Blob(blobBytes)
171+
return &b, nil
165172
}
166173

167174
type GenesisResp struct {
@@ -176,22 +183,6 @@ type SpecResp struct {
176183
} `json:"data"`
177184
}
178185

179-
type BlobSidecarResp struct {
180-
Data []struct {
181-
Index string `json:"index"`
182-
Blob string `json:"blob"`
183-
KzgCommitment string `json:"kzg_commitment"`
184-
KzgProof string `json:"kzg_proof"`
185-
SignedBlockHeader struct {
186-
Message struct {
187-
Slot string `json:"slot"`
188-
ProposerIndex string `json:"proposer_index"`
189-
ParentRoot string `json:"parent_root"`
190-
StateRoot string `json:"state_root"`
191-
BodyRoot string `json:"body_root"`
192-
} `json:"message"`
193-
Signature string `json:"signature"`
194-
} `json:"signed_block_header"`
195-
KzgCommitmentInclusionProof []string `json:"kzg_commitment_inclusion_proof"`
196-
} `json:"data"`
186+
type BlobsResp struct {
187+
Data []string `json:"data"` // array of blobs as hex strings
197188
}

rollup/da_syncer/blob_client/blob_client.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import (
1212
)
1313

1414
const (
15-
lenBlobBytes int = 131072
16-
lenKZGCommitment int = 48
15+
lenBlobBytes int = 131072
1716
)
1817

1918
type BlobClient interface {

0 commit comments

Comments
 (0)