Skip to content

Commit 925ef74

Browse files
author
colinlyguo
committed
add sanity checks in calldata and blob
1 parent 1b28ff5 commit 925ef74

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

rollup/internal/controller/relayer/l2_relayer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,12 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
526526
log.Error("failed to construct normal payload", "codecVersion", codecVersion, "start index", firstBatch.Index, "end index", lastBatch.Index, "err", err)
527527
return
528528
}
529+
530+
err = r.sanityChecksCommitBatchCodecV7CalldataAndBlobs(calldata, blobs, batchesToSubmit, firstBatch, lastBatch)
531+
if err != nil {
532+
log.Error("Sanity check failed for calldata and blobs", "err", err)
533+
return
534+
}
529535
}
530536
default:
531537
log.Error("unsupported codec version in ProcessPendingBatches", "codecVersion", codecVersion, "start index", firstBatch, "end index", lastBatch.Index)

rollup/internal/controller/relayer/l2_relayer_sanity.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package relayer
33
import (
44
"fmt"
55

6+
"github.com/scroll-tech/da-codec/encoding"
67
"github.com/scroll-tech/go-ethereum/common"
8+
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
79
"github.com/scroll-tech/go-ethereum/log"
810

911
"scroll-tech/rollup/internal/orm"
@@ -245,3 +247,104 @@ func (r *Layer2Relayer) validateSingleChunk(chunk *orm.Chunk, prevChunk *orm.Chu
245247

246248
return nil
247249
}
250+
251+
func (r *Layer2Relayer) sanityChecksCommitBatchCodecV7CalldataAndBlobs(calldata []byte, blobs []*kzg4844.Blob, batchesToSubmit []*dbBatchWithChunks, firstBatch, lastBatch *orm.Batch,
252+
) error {
253+
// Check blob count matches batch count
254+
if len(blobs) != len(batchesToSubmit) {
255+
return fmt.Errorf("blob count mismatch: got %d, want %d", len(blobs), len(batchesToSubmit))
256+
}
257+
258+
// Parse calldata (after first 4 bytes: method selector)
259+
method := r.l1RollupABI.Methods["commitBatches"]
260+
if len(calldata) < 4 {
261+
return fmt.Errorf("calldata too short to contain method selector")
262+
}
263+
decoded, err := method.Inputs.Unpack(calldata[4:])
264+
if err != nil {
265+
return fmt.Errorf("failed to unpack commitBatches calldata: %w", err)
266+
}
267+
268+
if len(decoded) != 3 {
269+
return fmt.Errorf("unexpected number of decoded parameters: got %d, want 3", len(decoded))
270+
}
271+
272+
version, ok := decoded[0].(uint8)
273+
if !ok {
274+
return fmt.Errorf("failed to type assert version to uint8")
275+
}
276+
parentBatchHashB, ok := decoded[1].([32]uint8)
277+
if !ok {
278+
return fmt.Errorf("failed to type assert parentBatchHash to [32]uint8")
279+
}
280+
parentBatchHash := common.BytesToHash(parentBatchHashB[:])
281+
lastBatchHashB, ok := decoded[2].([32]uint8)
282+
if !ok {
283+
return fmt.Errorf("failed to type assert lastBatchHash to [32]uint8")
284+
}
285+
lastBatchHash := common.BytesToHash(lastBatchHashB[:])
286+
287+
// Check version and batch hashes
288+
if version != uint8(firstBatch.CodecVersion) {
289+
return fmt.Errorf("sanity check failed: version mismatch: calldata=%d, db=%d", version, firstBatch.CodecVersion)
290+
}
291+
if parentBatchHash != common.HexToHash(firstBatch.ParentBatchHash) {
292+
return fmt.Errorf("sanity check failed: parentBatchHash mismatch: calldata=%s, db=%s", parentBatchHash.Hex(), firstBatch.ParentBatchHash)
293+
}
294+
if lastBatchHash != common.HexToHash(lastBatch.Hash) {
295+
return fmt.Errorf("sanity check failed: lastBatchHash mismatch: calldata=%s, db=%s", lastBatchHash.Hex(), lastBatch.Hash)
296+
}
297+
298+
// Get codec for blob decoding
299+
codec, err := encoding.CodecFromVersion(encoding.CodecVersion(firstBatch.CodecVersion))
300+
if err != nil {
301+
return fmt.Errorf("failed to get codec: %w", err)
302+
}
303+
304+
// Loop through each batch and blob, decode and compare
305+
for i, blob := range blobs {
306+
dbBatch := batchesToSubmit[i].Batch
307+
dbChunks := batchesToSubmit[i].Chunks
308+
309+
// Collect all blocks for the batch
310+
var batchBlocks []*encoding.Block
311+
for _, c := range dbChunks {
312+
blocks, err := r.l2BlockOrm.GetL2BlocksInRange(r.ctx, c.StartBlockNumber, c.EndBlockNumber)
313+
if err != nil {
314+
return fmt.Errorf("failed to get blocks for batch %d chunk %d: %w", dbBatch.Index, c.Index, err)
315+
}
316+
batchBlocks = append(batchBlocks, blocks...)
317+
}
318+
319+
// Decode blob payload
320+
payload, err := codec.DecodeBlob(blob)
321+
if err != nil {
322+
return fmt.Errorf("failed to decode blob for batch %d: %w", dbBatch.Index, err)
323+
}
324+
325+
// Check L1 message queue hashes
326+
if payload.PrevL1MessageQueueHash() != common.HexToHash(dbBatch.PrevL1MessageQueueHash) {
327+
return fmt.Errorf("sanity check failed: prevL1MessageQueueHash mismatch for batch %d: decoded=%s, db=%s",
328+
dbBatch.Index, payload.PrevL1MessageQueueHash().Hex(), dbBatch.PrevL1MessageQueueHash)
329+
}
330+
if payload.PostL1MessageQueueHash() != common.HexToHash(dbBatch.PostL1MessageQueueHash) {
331+
return fmt.Errorf("sanity check failed: postL1MessageQueueHash mismatch for batch %d: decoded=%s, db=%s",
332+
dbBatch.Index, payload.PostL1MessageQueueHash().Hex(), dbBatch.PostL1MessageQueueHash)
333+
}
334+
335+
// Compare block count and block numbers
336+
decodedBlocks := payload.Blocks()
337+
if len(decodedBlocks) != len(batchBlocks) {
338+
return fmt.Errorf("sanity check failed: block count mismatch in batch %d: decoded=%d, db=%d", dbBatch.Index, len(decodedBlocks), len(batchBlocks))
339+
}
340+
for j, b := range batchBlocks {
341+
if decodedBlocks[j].Number() != b.Header.Number.Uint64() {
342+
return fmt.Errorf("sanity check failed: block number mismatch in batch %d block %d: decoded=%d, db=%d",
343+
dbBatch.Index, j, decodedBlocks[j].Number(), b.Header.Number.Uint64())
344+
}
345+
}
346+
}
347+
348+
// All checks passed
349+
return nil
350+
}

0 commit comments

Comments
 (0)