Skip to content

Commit 24f541c

Browse files
authored
feat: add da blob client aws s3 (#1209)
* feat: add blob client aws s3 * go mod tidy * chore: auto version bump [bot]
1 parent 1043f66 commit 24f541c

File tree

7 files changed

+97
-1
lines changed

7 files changed

+97
-1
lines changed

cmd/geth/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ var (
182182
utils.DABlockNativeAPIEndpointFlag,
183183
utils.DABlobScanAPIEndpointFlag,
184184
utils.DABeaconNodeAPIEndpointFlag,
185+
utils.DAAwsS3BlobAPIEndpointFlag,
185186
utils.DARecoveryModeFlag,
186187
utils.DARecoveryInitialL1BlockFlag,
187188
utils.DARecoveryInitialBatchFlag,

cmd/geth/usage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
240240
utils.DABlobScanAPIEndpointFlag,
241241
utils.DABlockNativeAPIEndpointFlag,
242242
utils.DABeaconNodeAPIEndpointFlag,
243+
utils.DAAwsS3BlobAPIEndpointFlag,
243244
utils.DARecoveryModeFlag,
244245
utils.DARecoveryInitialL1BlockFlag,
245246
utils.DARecoveryInitialBatchFlag,

cmd/utils/flags.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,10 @@ var (
920920
Name: "da.blob.beaconnode",
921921
Usage: "Beacon node API endpoint",
922922
}
923+
DAAwsS3BlobAPIEndpointFlag = cli.StringFlag{
924+
Name: "da.blob.awss3",
925+
Usage: "AWS S3 blob API endpoint",
926+
}
923927
DARecoveryModeFlag = cli.BoolFlag{
924928
Name: "da.recovery",
925929
Usage: "Enable recovery mode for DA syncing",
@@ -1699,6 +1703,9 @@ func setDA(ctx *cli.Context, cfg *ethconfig.Config) {
16991703
if ctx.IsSet(DABeaconNodeAPIEndpointFlag.Name) {
17001704
cfg.DA.BeaconNodeAPIEndpoint = ctx.String(DABeaconNodeAPIEndpointFlag.Name)
17011705
}
1706+
if ctx.IsSet(DAAwsS3BlobAPIEndpointFlag.Name) {
1707+
cfg.DA.AwsS3BlobAPIEndpoint = ctx.String(DAAwsS3BlobAPIEndpointFlag.Name)
1708+
}
17021709
if ctx.IsSet(DARecoveryModeFlag.Name) {
17031710
cfg.DA.RecoveryMode = ctx.Bool(DARecoveryModeFlag.Name)
17041711
}

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 = 8 // Minor version component of the current release
27-
VersionPatch = 64 // Patch version component of the current release
27+
VersionPatch = 65 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package blob_client
2+
3+
import (
4+
"context"
5+
"crypto/sha256"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"net/url"
10+
"time"
11+
12+
"github.com/scroll-tech/go-ethereum/common"
13+
"github.com/scroll-tech/go-ethereum/common/hexutil"
14+
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
15+
)
16+
17+
const (
18+
AwsS3DefaultTimeout = 15 * time.Second
19+
)
20+
21+
type AwsS3Client struct {
22+
client *http.Client
23+
apiEndpoint string
24+
}
25+
26+
func NewAwsS3Client(apiEndpoint string) *AwsS3Client {
27+
return &AwsS3Client{
28+
apiEndpoint: apiEndpoint,
29+
client: &http.Client{Timeout: AwsS3DefaultTimeout},
30+
}
31+
}
32+
33+
func (c *AwsS3Client) GetBlobByVersionedHashAndBlockTime(ctx context.Context, versionedHash common.Hash, blockTime uint64) (*kzg4844.Blob, error) {
34+
// Scroll mainnet blob data AWS S3 endpoint: https://scroll-mainnet-blob-data.s3.us-west-2.amazonaws.com/
35+
// Scroll sepolia blob data AWS S3 endpoint: https://scroll-sepolia-blob-data.s3.us-west-2.amazonaws.com/
36+
path, err := url.JoinPath(c.apiEndpoint, versionedHash.String())
37+
if err != nil {
38+
return nil, fmt.Errorf("failed to join path, err: %w", err)
39+
}
40+
req, err := http.NewRequestWithContext(ctx, "GET", path, nil)
41+
if err != nil {
42+
return nil, fmt.Errorf("cannot create request, err: %w", err)
43+
}
44+
resp, err := c.client.Do(req)
45+
if err != nil {
46+
return nil, fmt.Errorf("cannot do request, err: %w", err)
47+
}
48+
defer resp.Body.Close()
49+
50+
if resp.StatusCode != http.StatusOK {
51+
body, err := io.ReadAll(resp.Body)
52+
if err != nil {
53+
return nil, fmt.Errorf("aws s3 request failed with status: %s: could not read response body: %w", resp.Status, err)
54+
}
55+
bodyStr := string(body)
56+
return nil, fmt.Errorf("aws s3 request failed, status: %s, body: %s", resp.Status, bodyStr)
57+
}
58+
59+
var blob kzg4844.Blob
60+
buf := blob[:]
61+
if n, err := io.ReadFull(resp.Body, buf); err != nil {
62+
if err == io.ErrUnexpectedEOF || err == io.EOF {
63+
return nil, fmt.Errorf("blob data too short: got %d bytes", n)
64+
}
65+
return nil, fmt.Errorf("failed to read blob data: %w", err)
66+
}
67+
68+
// sanity check that retrieved blob matches versioned hash
69+
commitment, err := kzg4844.BlobToCommitment(&blob)
70+
if err != nil {
71+
return nil, fmt.Errorf("failed to convert blob to commitment, err: %w", err)
72+
}
73+
74+
blobVersionedHash := kzg4844.CalcBlobHashV1(sha256.New(), &commitment)
75+
if blobVersionedHash != versionedHash {
76+
return nil, fmt.Errorf("blob versioned hash mismatch, expected: %s, got: %s", versionedHash.String(), hexutil.Encode(blobVersionedHash[:]))
77+
}
78+
79+
return &blob, nil
80+
}

rollup/da_syncer/syncing_pipeline.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Config struct {
2323
BlobScanAPIEndpoint string // BlobScan blob api endpoint
2424
BlockNativeAPIEndpoint string // BlockNative blob api endpoint
2525
BeaconNodeAPIEndpoint string // Beacon node api endpoint
26+
AwsS3BlobAPIEndpoint string // AWS S3 blob data api endpoint
2627

2728
RecoveryMode bool // Recovery mode is used to override existing blocks with the blocks read from the pipeline and start from a specific L1 block and batch
2829
InitialL1Block uint64 // L1 block in which the InitialBatch was committed (or any earlier L1 block but requires more RPC requests)
@@ -74,6 +75,9 @@ func NewSyncingPipeline(ctx context.Context, blockchain *core.BlockChain, genesi
7475
if config.BlockNativeAPIEndpoint != "" {
7576
blobClientList.AddBlobClient(blob_client.NewBlockNativeClient(config.BlockNativeAPIEndpoint))
7677
}
78+
if config.AwsS3BlobAPIEndpoint != "" {
79+
blobClientList.AddBlobClient(blob_client.NewAwsS3Client(config.AwsS3BlobAPIEndpoint))
80+
}
7781
if blobClientList.Size() == 0 {
7882
return nil, errors.New("DA syncing is enabled but no blob client is configured. Please provide at least one blob client via command line flag")
7983
}

rollup/rollup_sync_service/rollup_sync_service.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ func NewRollupSyncService(ctx context.Context, genesisConfig *params.ChainConfig
114114
if config.BlockNativeAPIEndpoint != "" {
115115
blobClientList.AddBlobClient(blob_client.NewBlockNativeClient(config.BlockNativeAPIEndpoint))
116116
}
117+
if config.AwsS3BlobAPIEndpoint != "" {
118+
blobClientList.AddBlobClient(blob_client.NewAwsS3Client(config.AwsS3BlobAPIEndpoint))
119+
}
117120
if blobClientList.Size() == 0 {
118121
return nil, errors.New("no blob client is configured for rollup verifier. Please provide at least one blob client via command line flag")
119122
}

0 commit comments

Comments
 (0)