@@ -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,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