Skip to content

Commit 77bba2d

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

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

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.sanityCheckCalldataAndBlobs(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: 87 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,88 @@ func (r *Layer2Relayer) validateSingleChunk(chunk *orm.Chunk, prevChunk *orm.Chu
245247

246248
return nil
247249
}
250+
251+
func (r *Layer2Relayer) sanityCheckCalldataAndBlobs(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+
version := decoded[0].(uint8)
268+
parentBatchHash := decoded[1].(common.Hash)
269+
lastBatchHash := decoded[2].(common.Hash)
270+
271+
// Check version and batch hashes
272+
if version != uint8(firstBatch.CodecVersion) {
273+
return fmt.Errorf("sanity check failed: version mismatch: calldata=%d, db=%d", version, firstBatch.CodecVersion)
274+
}
275+
if parentBatchHash != common.HexToHash(firstBatch.ParentBatchHash) {
276+
return fmt.Errorf("sanity check failed: parentBatchHash mismatch: calldata=%s, db=%s", parentBatchHash.Hex(), firstBatch.ParentBatchHash)
277+
}
278+
if lastBatchHash != common.HexToHash(lastBatch.Hash) {
279+
return fmt.Errorf("sanity check failed: lastBatchHash mismatch: calldata=%s, db=%s", lastBatchHash.Hex(), lastBatch.Hash)
280+
}
281+
282+
// Get codec for blob decoding
283+
codec, err := encoding.CodecFromVersion(encoding.CodecVersion(firstBatch.CodecVersion))
284+
if err != nil {
285+
return fmt.Errorf("failed to get codec: %w", err)
286+
}
287+
288+
// Loop through each batch and blob, decode and compare
289+
for i, blob := range blobs {
290+
dbBatch := batchesToSubmit[i].Batch
291+
dbChunks := batchesToSubmit[i].Chunks
292+
293+
// Collect all blocks for the batch
294+
var batchBlocks []*encoding.Block
295+
for _, c := range dbChunks {
296+
blocks, err := r.l2BlockOrm.GetL2BlocksInRange(r.ctx, c.StartBlockNumber, c.EndBlockNumber)
297+
if err != nil {
298+
return fmt.Errorf("failed to get blocks for batch %d chunk %d: %w", dbBatch.Index, c.Index, err)
299+
}
300+
batchBlocks = append(batchBlocks, blocks...)
301+
}
302+
303+
// Decode blob payload
304+
payload, err := codec.DecodeBlob(blob)
305+
if err != nil {
306+
return fmt.Errorf("failed to decode blob for batch %d: %w", dbBatch.Index, err)
307+
}
308+
309+
// Check L1 message queue hashes
310+
if payload.PrevL1MessageQueueHash() != common.HexToHash(dbBatch.PrevL1MessageQueueHash) {
311+
return fmt.Errorf("sanity check failed: prevL1MessageQueueHash mismatch for batch %d: decoded=%s, db=%s",
312+
dbBatch.Index, payload.PrevL1MessageQueueHash().Hex(), dbBatch.PrevL1MessageQueueHash)
313+
}
314+
if payload.PostL1MessageQueueHash() != common.HexToHash(dbBatch.PostL1MessageQueueHash) {
315+
return fmt.Errorf("sanity check failed: postL1MessageQueueHash mismatch for batch %d: decoded=%s, db=%s",
316+
dbBatch.Index, payload.PostL1MessageQueueHash().Hex(), dbBatch.PostL1MessageQueueHash)
317+
}
318+
319+
// Compare block count and block numbers
320+
decodedBlocks := payload.Blocks()
321+
if len(decodedBlocks) != len(batchBlocks) {
322+
return fmt.Errorf("sanity check failed: block count mismatch in batch %d: decoded=%d, db=%d", dbBatch.Index, len(decodedBlocks), len(batchBlocks))
323+
}
324+
for j, b := range batchBlocks {
325+
if decodedBlocks[j].Number() != b.Header.Number.Uint64() {
326+
return fmt.Errorf("sanity check failed: block number mismatch in batch %d block %d: decoded=%d, db=%d",
327+
dbBatch.Index, j, decodedBlocks[j].Number(), b.Header.Number.Uint64())
328+
}
329+
}
330+
}
331+
332+
// All checks passed
333+
return nil
334+
}

0 commit comments

Comments
 (0)