Skip to content

Commit 034a6c7

Browse files
authored
dac: max blob size (#1385)
<!-- Please read and fill out this form before submitting your PR. Please make sure you have reviewed our contributors guide before submitting your first PR. --> ## Overview Fixes #1233 <!-- Please provide an explanation of the PR, including the appropriate context, background, goal, and rationale. If there is an issue with this information, please provide a tl;dr and link the issue. --> ## Checklist <!-- Please complete the checklist to ensure that the PR is ready to be reviewed. IMPORTANT: PRs should be left in Draft until the below checklist is completed. --> - [x] New and updated code has appropriate documentation - [x] New and updated code has new and/or updated testing - [x] Required CI checks are passing - [x] Visual proof for any user facing features like CLI or documentation updates - [x] Linked issues closed with keywords Depends on evstack/go-da#23 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved block submission process with retries and exponential backoff for increased reliability. - Added error handling for block size limitations and existence issues during submission. - **Enhancements** - Block submission now includes a count of successfully submitted blocks for better tracking. - Partial reset functionality added to the management of pending blocks based on submission status. - **Bug Fixes** - Fixed an issue where block submission could fail silently by ensuring all pending blocks are confirmed as submitted before completion. - **Documentation** - Updated function documentation to reflect new error handling and submission count features. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents ff62618 + b73afcf commit 034a6c7

7 files changed

Lines changed: 255 additions & 48 deletions

File tree

block/manager.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -738,21 +738,26 @@ func (m *Manager) submitBlocksToDA(ctx context.Context) error {
738738
submitted := false
739739
backoff := initialBackoff
740740
for attempt := 1; ctx.Err() == nil && !submitted && attempt <= maxSubmitAttempts; attempt++ {
741-
res := m.dalc.SubmitBlocks(ctx, m.pendingBlocks.getPendingBlocks())
742-
if res.Code == da.StatusSuccess {
743-
m.logger.Info("successfully submitted Rollkit block to DA layer", "daHeight", res.DAHeight)
744-
submitted = true
745-
} else {
741+
blocks := m.pendingBlocks.getPendingBlocks()
742+
res := m.dalc.SubmitBlocks(ctx, blocks)
743+
switch res.Code {
744+
case da.StatusSuccess:
745+
m.logger.Info("successfully submitted Rollkit block to DA layer", "daHeight", res.DAHeight, "count", res.SubmittedCount)
746+
if int(res.SubmittedCount) == len(blocks) {
747+
submitted = true
748+
}
749+
m.pendingBlocks.resetPendingBlocks(res.SubmittedCount)
750+
case da.StatusError, da.StatusNotFound, da.StatusUnknown:
746751
m.logger.Error("DA layer submission failed", "error", res.Message, "attempt", attempt)
747752
time.Sleep(backoff)
748753
backoff = m.exponentialBackoff(backoff)
754+
default:
749755
}
750756
}
751757

752758
if !submitted {
753759
return fmt.Errorf("failed to submit block to DA layer after %d attempts", maxSubmitAttempts)
754760
}
755-
m.pendingBlocks.resetPendingBlocks()
756761
return nil
757762
}
758763

block/pending_blocks.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ func (pb *PendingBlocks) addPendingBlock(block *types.Block) {
3737
pb.pendingBlocks = append(pb.pendingBlocks, block)
3838
}
3939

40-
func (pb *PendingBlocks) resetPendingBlocks() {
40+
func (pb *PendingBlocks) resetPendingBlocks(submitted uint64) {
4141
pb.mtx.Lock()
4242
defer pb.mtx.Unlock()
43-
pb.pendingBlocks = make([]*types.Block, 0)
43+
if submitted > uint64(len(pb.pendingBlocks)) {
44+
submitted = uint64(len(pb.pendingBlocks))
45+
}
46+
pb.pendingBlocks = pb.pendingBlocks[submitted:]
4447
}

da/da.go

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ import (
1414
pb "github.com/rollkit/rollkit/types/pb/rollkit"
1515
)
1616

17-
// ErrBlobNotFound is used to indicate that the blob was not found.
18-
var ErrBlobNotFound = errors.New("blob: not found")
17+
var (
18+
// ErrBlobNotFound is used to indicate that the blob was not found.
19+
ErrBlobNotFound = errors.New("blob: not found")
20+
21+
// ErrBlobSizeOverLimit is used to indicate that the blob size is over limit
22+
ErrBlobSizeOverLimit = errors.New("blob: over size limit")
23+
)
1924

2025
// StatusCode is a type for DA layer return status.
2126
// TODO: define an enum of different non-happy-path cases
@@ -39,6 +44,8 @@ type BaseResult struct {
3944
Message string
4045
// DAHeight informs about a height on Data Availability Layer for given result.
4146
DAHeight uint64
47+
// SubmittedCount is the number of successfully submitted blocks.
48+
SubmittedCount uint64
4249
}
4350

4451
// ResultSubmitBlocks contains information returned from DA layer after blocks submission.
@@ -65,7 +72,18 @@ type DAClient struct {
6572

6673
// SubmitBlocks submits blocks to DA.
6774
func (dac *DAClient) SubmitBlocks(ctx context.Context, blocks []*types.Block) ResultSubmitBlocks {
68-
blobs := make([][]byte, len(blocks))
75+
var blobs [][]byte
76+
var blobSize uint64
77+
maxBlobSize, err := dac.DA.MaxBlobSize()
78+
if err != nil {
79+
return ResultSubmitBlocks{
80+
BaseResult: BaseResult{
81+
Code: StatusError,
82+
Message: "unable to get DA max blob size",
83+
},
84+
}
85+
}
86+
var submitted uint64
6987
for i := range blocks {
7088
blob, err := blocks[i].MarshalBinary()
7189
if err != nil {
@@ -76,7 +94,21 @@ func (dac *DAClient) SubmitBlocks(ctx context.Context, blocks []*types.Block) Re
7694
},
7795
}
7896
}
79-
blobs[i] = blob
97+
if blobSize+uint64(len(blob)) > maxBlobSize {
98+
dac.Logger.Info("blob size limit reached", "maxBlobSize", maxBlobSize, "index", i, "blobSize", blobSize, "len(blob)", len(blob))
99+
break
100+
}
101+
blobSize += uint64(len(blob))
102+
submitted += 1
103+
blobs = append(blobs, blob)
104+
}
105+
if submitted == 0 {
106+
return ResultSubmitBlocks{
107+
BaseResult: BaseResult{
108+
Code: StatusError,
109+
Message: "failed to submit blocks: oversized block: " + ErrBlobSizeOverLimit.Error(),
110+
},
111+
}
80112
}
81113
ids, _, err := dac.DA.Submit(blobs)
82114
if err != nil {
@@ -88,10 +120,20 @@ func (dac *DAClient) SubmitBlocks(ctx context.Context, blocks []*types.Block) Re
88120
}
89121
}
90122

123+
if len(ids) == 0 {
124+
return ResultSubmitBlocks{
125+
BaseResult: BaseResult{
126+
Code: StatusError,
127+
Message: "failed to submit blocks: unexpected len(ids): 0",
128+
},
129+
}
130+
}
131+
91132
return ResultSubmitBlocks{
92133
BaseResult: BaseResult{
93-
Code: StatusSuccess,
94-
DAHeight: binary.LittleEndian.Uint64(ids[0]),
134+
Code: StatusSuccess,
135+
DAHeight: binary.LittleEndian.Uint64(ids[0]),
136+
SubmittedCount: submitted,
95137
},
96138
}
97139
}

da/da.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Rollkit provides a wrapper for [go-da][go-da], a generic data availability inter
88

99
Given a set of blocks to be submitted to DA by the block manager, the `SubmitBlocks` first encodes the blocks using protobuf (the encoded data are called blobs) and invokes the `Submit` method on the underlying DA implementation. On successful submission (`StatusSuccess`), the DA block height which included in the rollup blocks is returned.
1010

11+
To make sure that the serialised blocks don't exceed the underlying DA's blob limits, it fetches the the blob size limit by calling `Config` which returns the limit as `uint64` bytes, then includes serialised blocks until the limit is reached. If the limit is reached, it submits the partial set and returns the count of successfully submitted blocks as `SubmittedCount`. The caller should retry with the remaining blocks until all the blocks are submitted. If the first block itself is over the limit, it throws an error.
12+
1113
The `Submit` call may result in an error (`StatusError`) based on the underlying DA implementations on following scenarios:
1214

1315
* the total blobs size exceeds the underlying DA's limits (includes empty blobs)

0 commit comments

Comments
 (0)