@@ -3,7 +3,9 @@ package relayer
3
3
import (
4
4
"fmt"
5
5
6
+ "github.com/scroll-tech/da-codec/encoding"
6
7
"github.com/scroll-tech/go-ethereum/common"
8
+ "github.com/scroll-tech/go-ethereum/crypto/kzg4844"
7
9
"github.com/scroll-tech/go-ethereum/log"
8
10
9
11
"scroll-tech/rollup/internal/orm"
@@ -245,3 +247,88 @@ func (r *Layer2Relayer) validateSingleChunk(chunk *orm.Chunk, prevChunk *orm.Chu
245
247
246
248
return nil
247
249
}
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