@@ -3,7 +3,9 @@ package relayer
33import (
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