|
8 | 8 | "github.com/prometheus/client_golang/prometheus" |
9 | 9 | "github.com/prometheus/client_golang/prometheus/promauto" |
10 | 10 | "github.com/scroll-tech/da-codec/encoding" |
| 11 | + "github.com/scroll-tech/go-ethereum/common" |
11 | 12 | "github.com/scroll-tech/go-ethereum/log" |
12 | 13 | "github.com/scroll-tech/go-ethereum/params" |
13 | 14 | "gorm.io/gorm" |
@@ -299,10 +300,49 @@ func (p *ChunkProposer) proposeChunk() error { |
299 | 300 | } |
300 | 301 |
|
301 | 302 | 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 |
302 | 332 | chunk.Blocks = make([]*encoding.Block, 0, len(blocks)) |
303 | 333 | for i, block := range blocks { |
304 | 334 | chunk.Blocks = append(chunk.Blocks, block) |
305 | 335 |
|
| 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 | + |
306 | 346 | metrics, calcErr := utils.CalculateChunkMetrics(&chunk, codecVersion) |
307 | 347 | if calcErr != nil { |
308 | 348 | return fmt.Errorf("failed to calculate chunk metrics: %w", calcErr) |
@@ -339,6 +379,7 @@ func (p *ChunkProposer) proposeChunk() error { |
339 | 379 | "maxUncompressedBatchBytesSize", p.maxUncompressedBatchBytesSize) |
340 | 380 |
|
341 | 381 | chunk.Blocks = chunk.Blocks[:len(chunk.Blocks)-1] |
| 382 | + chunk.LastL1MessageQueueHash = previousLastL1MessageQueueHash |
342 | 383 |
|
343 | 384 | metrics, calcErr := utils.CalculateChunkMetrics(&chunk, codecVersion) |
344 | 385 | if calcErr != nil { |
|
0 commit comments