Skip to content

Commit 310abdd

Browse files
committed
add InitialL1MessageQueueHash and LastL1MessageQueueHash to chunk and batch
1 parent 5a479c3 commit 310abdd

File tree

8 files changed

+113
-28
lines changed

8 files changed

+113
-28
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- +goose Up
2+
-- +goose StatementBegin
3+
4+
ALTER TABLE chunk
5+
ADD COLUMN initial_l1_message_queue_hash VARCHAR DEFAULT '';
6+
ADD COLUMN last_l1_message_queue_hash VARCHAR DEFAULT '';
7+
8+
ALTER TABLE batch
9+
ADD COLUMN initial_l1_message_queue_hash VARCHAR DEFAULT '';
10+
ADD COLUMN last_l1_message_queue_hash VARCHAR DEFAULT '';
11+
12+
13+
-- +goose StatementEnd
14+
15+
-- +goose Down
16+
-- +goose StatementBegin
17+
18+
ALTER TABLE IF EXISTS chunk
19+
DROP COLUMN IF EXISTS initial_l1_message_queue_hash;
20+
DROP COLUMN IF EXISTS last_l1_message_queue_hash;
21+
22+
ALTER TABLE IF EXISTS batch
23+
DROP COLUMN IF EXISTS initial_l1_message_queue_hash;
24+
DROP COLUMN IF EXISTS last_l1_message_queue_hash;
25+
26+
-- +goose StatementEnd

rollup/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/holiman/uint256 v1.3.2
1414
github.com/mitchellh/mapstructure v1.5.0
1515
github.com/prometheus/client_golang v1.16.0
16-
github.com/scroll-tech/da-codec v0.1.3-0.20250205011841-edaf5d2f9f24
16+
github.com/scroll-tech/da-codec v0.1.3-0.20250205043214-894a93bb6b53
1717
github.com/scroll-tech/go-ethereum v1.10.14-0.20250129031936-44c72cd3fa47
1818
github.com/smartystreets/goconvey v1.8.0
1919
github.com/spf13/viper v1.19.0

rollup/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ github.com/scroll-tech/da-codec v0.1.3-0.20250128015324-64133efc3843 h1:Qd6bh5Cn
253253
github.com/scroll-tech/da-codec v0.1.3-0.20250128015324-64133efc3843/go.mod h1:+ho/ItbapMf2xM9YUv/SfGFg3AJx9lBD7ksR7T0ZVmM=
254254
github.com/scroll-tech/da-codec v0.1.3-0.20250205011841-edaf5d2f9f24 h1:E+DYPJPoIxviTfyjttoHoZ0ylv2n9fNHHwTK6n4vCss=
255255
github.com/scroll-tech/da-codec v0.1.3-0.20250205011841-edaf5d2f9f24/go.mod h1:irqXJdRI5fsGkilJCpNTnJb8oV8KR51j68QXIWoth6U=
256+
github.com/scroll-tech/da-codec v0.1.3-0.20250205043214-894a93bb6b53 h1:07eHUuUhQ2rOP6ij5+KV1MgQurkwyweomkxp5nAG6o8=
257+
github.com/scroll-tech/da-codec v0.1.3-0.20250205043214-894a93bb6b53/go.mod h1:irqXJdRI5fsGkilJCpNTnJb8oV8KR51j68QXIWoth6U=
256258
github.com/scroll-tech/go-ethereum v1.10.14-0.20250103082839-ea3ec93d8c1e h1:g8jtcGiHbjWYh/V7O245IDho3WfQT4CwEpBV+MhYDrg=
257259
github.com/scroll-tech/go-ethereum v1.10.14-0.20250103082839-ea3ec93d8c1e/go.mod h1:Ik3OBLl7cJxPC+CFyCBYNXBPek4wpdzkWehn/y5qLM8=
258260
github.com/scroll-tech/go-ethereum v1.10.14-0.20250129031936-44c72cd3fa47/go.mod h1:8WbNuuUjie/LTdFXGGT7Z711MRW8Vv2zWLrcibg7hDc=

rollup/internal/controller/relayer/l2_relayer.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
537537
r.metrics.rollupL2RelayerCommitThroughput.Add(float64(totalGasUsed))
538538
r.metrics.rollupL2RelayerProcessPendingBatchSuccessTotal.Add(float64(len(batchesToSubmit)))
539539
r.metrics.rollupL2RelayerProcessBatchesPerTxCount.Set(float64(len(batchesToSubmit)))
540-
540+
541541
log.Info("Sent the commitBatches tx to layer1", "batches count", len(batchesToSubmit), "start index", firstBatch.Index, "start hash", firstBatch.Hash, "end index", lastBatch.Index, "end hash", lastBatch.Hash, "tx hash", txHash.String())
542542
}
543543

@@ -1097,13 +1097,14 @@ func (r *Layer2Relayer) constructCommitBatchPayloadCodecV7(batchesToSubmit []*db
10971097
firstParentBatch = b.ParentBatch
10981098
}
10991099

1100-
chunks := make([]*encoding.Chunk, len(b.Chunks))
1101-
for i, c := range b.Chunks {
1100+
var batchBlocks []*encoding.Block
1101+
for _, c := range b.Chunks {
11021102
blocks, err := r.l2BlockOrm.GetL2BlocksInRange(r.ctx, c.StartBlockNumber, c.EndBlockNumber)
11031103
if err != nil {
11041104
return nil, nil, 0, 0, fmt.Errorf("failed to get blocks in range for batch %d: %w", b.Batch.Index, err)
11051105
}
1106-
chunks[i] = &encoding.Chunk{Blocks: blocks}
1106+
1107+
batchBlocks = append(batchBlocks, blocks...)
11071108

11081109
if c.EndBlockNumber > maxBlockHeight {
11091110
maxBlockHeight = c.EndBlockNumber
@@ -1112,10 +1113,12 @@ func (r *Layer2Relayer) constructCommitBatchPayloadCodecV7(batchesToSubmit []*db
11121113
}
11131114

11141115
encodingBatch := &encoding.Batch{
1115-
Index: b.Batch.Index,
1116-
TotalL1MessagePoppedBefore: b.Chunks[0].TotalL1MessagesPoppedBefore,
1117-
ParentBatchHash: common.HexToHash(b.ParentBatch.Hash),
1118-
Chunks: chunks,
1116+
Index: b.Batch.Index,
1117+
ParentBatchHash: common.HexToHash(b.ParentBatch.Hash),
1118+
InitialL1MessageIndex: b.Chunks[0].TotalL1MessagesPoppedBefore,
1119+
InitialL1MessageQueueHash: common.HexToHash(b.Batch.InitialL1MessageQueueHash),
1120+
LastL1MessageQueueHash: common.HexToHash(b.Batch.LastL1MessageQueueHash),
1121+
Blocks: batchBlocks,
11191122
}
11201123

11211124
codec, err := encoding.CodecFromVersion(version)

rollup/internal/controller/watcher/batch_proposer.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ func (p *BatchProposer) proposeBatch() error {
253253
return fmt.Errorf("unsupported codec version: %v, expected at least %v", codec.Version(), p.minCodecVersion)
254254
}
255255

256+
// TODO: should we limit this here for performance reasons with a config parameter? CodecV7 in principle supports endless chunks and returns math.MaxInt here.
256257
maxChunksThisBatch := codec.MaxNumChunksPerBatch()
257258

258259
// select at most maxChunkNumPerBatch chunks
@@ -291,9 +292,12 @@ func (p *BatchProposer) proposeBatch() error {
291292
batch.Index = dbParentBatch.Index + 1
292293
batch.ParentBatchHash = common.HexToHash(dbParentBatch.Hash)
293294
batch.TotalL1MessagePoppedBefore = firstUnbatchedChunk.TotalL1MessagesPoppedBefore
295+
batch.InitialL1MessageQueueHash = common.HexToHash(firstUnbatchedChunk.InitialL1MessageQueueHash)
294296

295297
for i, chunk := range daChunks {
296298
batch.Chunks = append(batch.Chunks, chunk)
299+
batch.LastL1MessageQueueHash = common.HexToHash(dbChunks[i].LastL1MessageQueueHash)
300+
297301
metrics, calcErr := utils.CalculateBatchMetrics(&batch, codec.Version())
298302
if calcErr != nil {
299303
return fmt.Errorf("failed to calculate batch metrics: %w", calcErr)
@@ -322,8 +326,9 @@ func (p *BatchProposer) proposeBatch() error {
322326
"maxUncompressedBatchBytesSize", p.maxUncompressedBatchBytesSize)
323327

324328
batch.Chunks = batch.Chunks[:len(batch.Chunks)-1]
329+
batch.LastL1MessageQueueHash = common.HexToHash(dbChunks[i-1].LastL1MessageQueueHash)
325330

326-
metrics, err := utils.CalculateBatchMetrics(&batch, codec.Version())
331+
metrics, err = utils.CalculateBatchMetrics(&batch, codec.Version())
327332
if err != nil {
328333
return fmt.Errorf("failed to calculate batch metrics: %w", err)
329334
}

rollup/internal/controller/watcher/chunk_proposer.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/prometheus/client_golang/prometheus"
99
"github.com/prometheus/client_golang/prometheus/promauto"
1010
"github.com/scroll-tech/da-codec/encoding"
11+
"github.com/scroll-tech/go-ethereum/common"
1112
"github.com/scroll-tech/go-ethereum/log"
1213
"github.com/scroll-tech/go-ethereum/params"
1314
"gorm.io/gorm"
@@ -299,10 +300,49 @@ func (p *ChunkProposer) proposeChunk() error {
299300
}
300301

301302
var chunk encoding.Chunk
303+
// From CodecV7 / EuclidV2 onwards we need to provide the InitialL1MessageQueueHash and LastL1MessageQueueHash.
304+
// InitialL1MessageQueueHash of the first chunk in the fork needs to be the empty hash.
305+
if codecVersion >= encoding.CodecV7 {
306+
parentChunk, err := p.chunkOrm.GetLatestChunk(context.Background())
307+
if err != nil || parentChunk == nil {
308+
return fmt.Errorf("failed to get parent chunk: %w", err)
309+
}
310+
311+
chunk.InitialL1MessageQueueHash = common.HexToHash(parentChunk.LastL1MessageQueueHash)
312+
313+
// previous chunk is not CodecV7, this means this is the first chunk of the fork.
314+
if encoding.CodecVersion(parentChunk.CodecVersion) < codecVersion {
315+
// double check with the previous block
316+
prevBlocks, err := p.l2BlockOrm.GetL2BlocksGEHeight(p.ctx, blocks[0].Header.Number.Uint64()-1, 1)
317+
if err != nil || len(prevBlocks) == 0 || prevBlocks[0].Header.Hash() != blocks[0].Header.ParentHash {
318+
return fmt.Errorf("failed to get parent block: %w", err)
319+
}
320+
// We expect the previous block to be not EuclidV2. If it is something went wrong.
321+
if p.chainCfg.IsEuclidV2(prevBlocks[0].Header.Time) {
322+
return fmt.Errorf("unexpected EuclidV2 block: %v, current block: %d, chunk version: %d, parent chunk version: %d, parent chunk index: %d", prevBlocks[0].Header.Number, blocks[0].Header.Number, codecVersion, parentChunk.CodecVersion, parentChunk.Index)
323+
}
324+
325+
chunk.InitialL1MessageQueueHash = common.Hash{}
326+
}
327+
328+
chunk.LastL1MessageQueueHash = chunk.InitialL1MessageQueueHash
329+
}
330+
331+
var previousLastL1MessageQueueHash common.Hash
302332
chunk.Blocks = make([]*encoding.Block, 0, len(blocks))
303333
for i, block := range blocks {
304334
chunk.Blocks = append(chunk.Blocks, block)
305335

336+
// Compute rolling LastL1MessageQueueHash for the chunk. Each block's L1 messages are applied to the previous
337+
// hash starting from the InitialL1MessageQueueHash for the chunk.
338+
if codecVersion >= encoding.CodecV7 {
339+
previousLastL1MessageQueueHash = chunk.LastL1MessageQueueHash
340+
chunk.LastL1MessageQueueHash, err = encoding.MessageQueueV2ApplyL1MessagesFromBlocks(chunk.LastL1MessageQueueHash, []*encoding.Block{block})
341+
if err != nil {
342+
return fmt.Errorf("failed to calculate last L1 message queue hash for block %d: %w", block.Header.Number.Uint64(), err)
343+
}
344+
}
345+
306346
metrics, calcErr := utils.CalculateChunkMetrics(&chunk, codecVersion)
307347
if calcErr != nil {
308348
return fmt.Errorf("failed to calculate chunk metrics: %w", calcErr)
@@ -339,6 +379,7 @@ func (p *ChunkProposer) proposeChunk() error {
339379
"maxUncompressedBatchBytesSize", p.maxUncompressedBatchBytesSize)
340380

341381
chunk.Blocks = chunk.Blocks[:len(chunk.Blocks)-1]
382+
chunk.LastL1MessageQueueHash = previousLastL1MessageQueueHash
342383

343384
metrics, calcErr := utils.CalculateChunkMetrics(&chunk, codecVersion)
344385
if calcErr != nil {

rollup/internal/orm/batch.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,22 @@ type Batch struct {
2323
db *gorm.DB `gorm:"column:-"`
2424

2525
// batch
26-
Index uint64 `json:"index" gorm:"column:index"`
27-
Hash string `json:"hash" gorm:"column:hash"`
28-
DataHash string `json:"data_hash" gorm:"column:data_hash"`
29-
StartChunkIndex uint64 `json:"start_chunk_index" gorm:"column:start_chunk_index"`
30-
StartChunkHash string `json:"start_chunk_hash" gorm:"column:start_chunk_hash"`
31-
EndChunkIndex uint64 `json:"end_chunk_index" gorm:"column:end_chunk_index"`
32-
EndChunkHash string `json:"end_chunk_hash" gorm:"column:end_chunk_hash"`
33-
StateRoot string `json:"state_root" gorm:"column:state_root"`
34-
WithdrawRoot string `json:"withdraw_root" gorm:"column:withdraw_root"`
35-
ParentBatchHash string `json:"parent_batch_hash" gorm:"column:parent_batch_hash"`
36-
BatchHeader []byte `json:"batch_header" gorm:"column:batch_header"`
37-
CodecVersion int16 `json:"codec_version" gorm:"column:codec_version"`
38-
EnableCompress bool `json:"enable_compress" gorm:"column:enable_compress"` // use for debug
39-
BlobBytes []byte `json:"blob_bytes" gorm:"column:blob_bytes"`
26+
Index uint64 `json:"index" gorm:"column:index"`
27+
Hash string `json:"hash" gorm:"column:hash"`
28+
DataHash string `json:"data_hash" gorm:"column:data_hash"`
29+
StartChunkIndex uint64 `json:"start_chunk_index" gorm:"column:start_chunk_index"`
30+
StartChunkHash string `json:"start_chunk_hash" gorm:"column:start_chunk_hash"`
31+
EndChunkIndex uint64 `json:"end_chunk_index" gorm:"column:end_chunk_index"`
32+
EndChunkHash string `json:"end_chunk_hash" gorm:"column:end_chunk_hash"`
33+
StateRoot string `json:"state_root" gorm:"column:state_root"`
34+
WithdrawRoot string `json:"withdraw_root" gorm:"column:withdraw_root"`
35+
ParentBatchHash string `json:"parent_batch_hash" gorm:"column:parent_batch_hash"`
36+
BatchHeader []byte `json:"batch_header" gorm:"column:batch_header"`
37+
CodecVersion int16 `json:"codec_version" gorm:"column:codec_version"`
38+
InitialL1MessageQueueHash string `json:"initial_l1_message_queue_hash" gorm:"column:initial_l1_message_queue_hash"`
39+
LastL1MessageQueueHash string `json:"last_l1_message_queue_hash" gorm:"column:last_l1_message_queue_hash"`
40+
EnableCompress bool `json:"enable_compress" gorm:"column:enable_compress"` // use for debug
41+
BlobBytes []byte `json:"blob_bytes" gorm:"column:blob_bytes"`
4042

4143
// proof
4244
ChunkProofsStatus int16 `json:"chunk_proofs_status" gorm:"column:chunk_proofs_status;default:1"`
@@ -298,6 +300,8 @@ func (o *Batch) InsertBatch(ctx context.Context, batch *encoding.Batch, codecVer
298300
ParentBatchHash: batch.ParentBatchHash.Hex(),
299301
BatchHeader: batchMeta.BatchBytes,
300302
CodecVersion: int16(codecVersion),
303+
InitialL1MessageQueueHash: batch.InitialL1MessageQueueHash.Hex(),
304+
LastL1MessageQueueHash: batch.LastL1MessageQueueHash.Hex(),
301305
EnableCompress: enableCompress,
302306
BlobBytes: batchMeta.BlobBytes,
303307
ChunkProofsStatus: int16(types.ChunkProofsStatusPending),

rollup/internal/orm/chunk.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type Chunk struct {
3030
StartBlockTime uint64 `json:"start_block_time" gorm:"column:start_block_time"`
3131
TotalL1MessagesPoppedBefore uint64 `json:"total_l1_messages_popped_before" gorm:"column:total_l1_messages_popped_before"`
3232
TotalL1MessagesPoppedInChunk uint64 `json:"total_l1_messages_popped_in_chunk" gorm:"column:total_l1_messages_popped_in_chunk"`
33+
InitialL1MessageQueueHash string `json:"initial_l1_message_queue_hash" gorm:"column:initial_l1_message_queue_hash"`
34+
LastL1MessageQueueHash string `json:"last_l1_message_queue_hash" gorm:"column:last_l1_message_queue_hash"`
3335
ParentChunkHash string `json:"parent_chunk_hash" gorm:"column:parent_chunk_hash"`
3436
StateRoot string `json:"state_root" gorm:"column:state_root"`
3537
ParentChunkStateRoot string `json:"parent_chunk_state_root" gorm:"column:parent_chunk_state_root"`
@@ -97,8 +99,8 @@ func (o *Chunk) GetChunksInRange(ctx context.Context, startIndex uint64, endInde
9799
return chunks, nil
98100
}
99101

100-
// getLatestChunk retrieves the latest chunk from the database.
101-
func (o *Chunk) getLatestChunk(ctx context.Context) (*Chunk, error) {
102+
// GetLatestChunk retrieves the latest chunk from the database.
103+
func (o *Chunk) GetLatestChunk(ctx context.Context) (*Chunk, error) {
102104
db := o.db.WithContext(ctx)
103105
db = db.Model(&Chunk{})
104106
db = db.Order("index desc")
@@ -116,7 +118,7 @@ func (o *Chunk) getLatestChunk(ctx context.Context) (*Chunk, error) {
116118
// GetUnchunkedBlockHeight retrieves the first unchunked block number.
117119
func (o *Chunk) GetUnchunkedBlockHeight(ctx context.Context) (uint64, error) {
118120
// Get the latest chunk
119-
latestChunk, err := o.getLatestChunk(ctx)
121+
latestChunk, err := o.GetLatestChunk(ctx)
120122
if err != nil {
121123
return 0, fmt.Errorf("Chunk.GetUnchunkedBlockHeight error: %w", err)
122124
}
@@ -187,7 +189,7 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, codecVer
187189
var totalL1MessagePoppedBefore uint64
188190
var parentChunkHash string
189191
var parentChunkStateRoot string
190-
parentChunk, err := o.getLatestChunk(ctx)
192+
parentChunk, err := o.GetLatestChunk(ctx)
191193
if err != nil {
192194
log.Error("failed to get latest chunk", "err", err)
193195
return nil, fmt.Errorf("Chunk.InsertChunk error: %w", err)
@@ -230,6 +232,8 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, codecVer
230232
StartBlockTime: chunk.Blocks[0].Header.Time,
231233
TotalL1MessagesPoppedBefore: totalL1MessagePoppedBefore,
232234
TotalL1MessagesPoppedInChunk: chunk.NumL1Messages(totalL1MessagePoppedBefore),
235+
InitialL1MessageQueueHash: chunk.InitialL1MessageQueueHash.Hex(),
236+
LastL1MessageQueueHash: chunk.LastL1MessageQueueHash.Hex(),
233237
ParentChunkHash: parentChunkHash,
234238
StateRoot: chunk.Blocks[numBlocks-1].Header.Root.Hex(),
235239
ParentChunkStateRoot: parentChunkStateRoot,

0 commit comments

Comments
 (0)