Skip to content

Commit 02b9229

Browse files
colinlyguoThegaram
authored andcommitted
feat(rollup): add fallback if TransactionByHash fails in getting commitBatch calldata (#601)
* feat(rollup): add fallback if TransactionByHash fails in getting commitBatch calldata * Update rollup/rollup_sync_service/rollup_sync_service.go Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * change log.Warn to log.Debug --------- Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
1 parent b521e62 commit 02b9229

File tree

5 files changed

+52
-27
lines changed

5 files changed

+52
-27
lines changed

core/rawdb/accessors_rollup_event.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type FinalizedBatchMeta struct {
2828
func WriteRollupEventSyncedL1BlockNumber(db ethdb.KeyValueWriter, l1BlockNumber uint64) {
2929
value := big.NewInt(0).SetUint64(l1BlockNumber).Bytes()
3030
if err := db.Put(rollupEventSyncedL1BlockNumberKey, value); err != nil {
31-
log.Crit("failed to store rollup event synced L1 block number for rollup event", "err", err)
31+
log.Crit("failed to store rollup event synced L1 block number for rollup event", "L1 block number", l1BlockNumber, "value", value, "err", err)
3232
}
3333
}
3434

@@ -44,7 +44,7 @@ func ReadRollupEventSyncedL1BlockNumber(db ethdb.Reader) *uint64 {
4444

4545
number := new(big.Int).SetBytes(data)
4646
if !number.IsUint64() {
47-
log.Crit("unexpected rollup event synced L1 block number in database", "number", number)
47+
log.Crit("unexpected rollup event synced L1 block number in database", "data", data, "number", number)
4848
}
4949

5050
rollupEventSyncedL1BlockNumber := number.Uint64()
@@ -54,12 +54,12 @@ func ReadRollupEventSyncedL1BlockNumber(db ethdb.Reader) *uint64 {
5454
// WriteBatchChunkRanges writes the block ranges for each chunk within a batch to the database.
5555
// It serializes the chunk ranges using RLP and stores them under a key derived from the batch index.
5656
func WriteBatchChunkRanges(db ethdb.KeyValueWriter, batchIndex uint64, chunkBlockRanges []*ChunkBlockRange) {
57-
bytes, err := rlp.EncodeToBytes(chunkBlockRanges)
57+
value, err := rlp.EncodeToBytes(chunkBlockRanges)
5858
if err != nil {
5959
log.Crit("failed to RLP encode batch chunk ranges", "batch index", batchIndex, "err", err)
6060
}
61-
if err := db.Put(batchChunkRangesKey(batchIndex), bytes); err != nil {
62-
log.Crit("failed to store batch chunk ranges", "batch index", batchIndex, "err", err)
61+
if err := db.Put(batchChunkRangesKey(batchIndex), value); err != nil {
62+
log.Crit("failed to store batch chunk ranges", "batch index", batchIndex, "value", value, "err", err)
6363
}
6464
}
6565

@@ -92,12 +92,12 @@ func ReadBatchChunkRanges(db ethdb.Reader, batchIndex uint64) []*ChunkBlockRange
9292
// WriteFinalizedBatchMeta stores the metadata of a finalized batch in the database.
9393
func WriteFinalizedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, finalizedBatchMeta *FinalizedBatchMeta) {
9494
var err error
95-
bytes, err := rlp.EncodeToBytes(finalizedBatchMeta)
95+
value, err := rlp.EncodeToBytes(finalizedBatchMeta)
9696
if err != nil {
97-
log.Crit("failed to RLP encode batch metadata", "batch index", batchIndex, "err", err)
97+
log.Crit("failed to RLP encode batch metadata", "batch index", batchIndex, "finalized batch meta", finalizedBatchMeta, "err", err)
9898
}
99-
if err := db.Put(batchMetaKey(batchIndex), bytes); err != nil {
100-
log.Crit("failed to store batch metadata", "batch index", batchIndex, "err", err)
99+
if err := db.Put(batchMetaKey(batchIndex), value); err != nil {
100+
log.Crit("failed to store batch metadata", "batch index", batchIndex, "value", value, "err", err)
101101
}
102102
}
103103

@@ -108,7 +108,7 @@ func ReadFinalizedBatchMeta(db ethdb.Reader, batchIndex uint64) *FinalizedBatchM
108108
return nil
109109
}
110110
if err != nil {
111-
log.Crit("failed to read finalized batch metadata from database", "err", err)
111+
log.Crit("failed to read finalized batch metadata from database", "batch index", batchIndex, "err", err)
112112
}
113113

114114
fbm := new(FinalizedBatchMeta)
@@ -122,7 +122,7 @@ func ReadFinalizedBatchMeta(db ethdb.Reader, batchIndex uint64) *FinalizedBatchM
122122
func WriteFinalizedL2BlockNumber(db ethdb.KeyValueWriter, l2BlockNumber uint64) {
123123
value := big.NewInt(0).SetUint64(l2BlockNumber).Bytes()
124124
if err := db.Put(finalizedL2BlockNumberKey, value); err != nil {
125-
log.Crit("failed to store finalized L2 block number for rollup event", "err", err)
125+
log.Crit("failed to store finalized L2 block number for rollup event", "L2 block number", l2BlockNumber, "value", value, "err", err)
126126
}
127127
}
128128

@@ -133,12 +133,12 @@ func ReadFinalizedL2BlockNumber(db ethdb.Reader) *uint64 {
133133
return nil
134134
}
135135
if err != nil {
136-
log.Crit("failed to read finalized L2 block number from database", "err", err)
136+
log.Crit("failed to read finalized L2 block number from database", "key", finalizedL2BlockNumberKey, "err", err)
137137
}
138138

139139
number := new(big.Int).SetBytes(data)
140140
if !number.IsUint64() {
141-
log.Crit("unexpected finalized L2 block number in database", "number", number)
141+
log.Crit("unexpected finalized L2 block number in database", "data", data, "number", number)
142142
}
143143

144144
finalizedL2BlockNumber := number.Uint64()

rollup/rollup_sync_service/chunk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func DecodeChunkBlockRanges(chunks [][]byte) ([]*rawdb.ChunkBlockRange, error) {
132132

133133
numBlocks := int(chunk[0])
134134
if len(chunk) < 1+numBlocks*blockContextByteSize {
135-
return nil, fmt.Errorf("chunk size doesn't match with numBlocks")
135+
return nil, fmt.Errorf("chunk size doesn't match with numBlocks, byte length of chunk: %v, expected length: %v", len(chunk), 1+numBlocks*blockContextByteSize)
136136
}
137137

138138
blockContexts := make([]*BlockContext, numBlocks)

rollup/rollup_sync_service/l1client_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@ func (m *mockEthClient) TransactionByHash(ctx context.Context, txHash common.Has
6868
}
6969
return &tx, false, nil
7070
}
71+
72+
func (m *mockEthClient) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
73+
return nil, nil
74+
}

rollup/rollup_sync_service/rollup_sync_service.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB
196196

197197
chunkBlockRanges, err := s.getChunkRanges(batchIndex, &vLog)
198198
if err != nil {
199-
return fmt.Errorf("failed to get chunk ranges, err: %w", err)
199+
return fmt.Errorf("failed to get chunk ranges, batch index: %v, err: %w", batchIndex, err)
200200
}
201201
rawdb.WriteBatchChunkRanges(s.db, batchIndex, chunkBlockRanges)
202202

@@ -311,9 +311,26 @@ func (s *RollupSyncService) getChunkRanges(batchIndex uint64, vLog *types.Log) (
311311
return []*rawdb.ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 0}}, nil
312312
}
313313

314-
tx, _, err := s.client.client.TransactionByHash(context.Background(), vLog.TxHash)
314+
tx, _, err := s.client.client.TransactionByHash(s.ctx, vLog.TxHash)
315315
if err != nil {
316-
return nil, fmt.Errorf("failed to get transaction, err: %w", err)
316+
log.Debug("failed to get transaction by hash, probably an unindexed transaction, fetching the whole block to get the transaction",
317+
"tx hash", vLog.TxHash.Hex(), "block number", vLog.BlockNumber, "block hash", vLog.BlockHash.Hex(), "err", err)
318+
block, err := s.client.client.BlockByHash(s.ctx, vLog.BlockHash)
319+
if err != nil {
320+
return nil, fmt.Errorf("failed to get block by hash, block number: %v, block hash: %v, err: %w", vLog.BlockNumber, vLog.BlockHash.Hex(), err)
321+
}
322+
323+
found := false
324+
for _, txInBlock := range block.Transactions() {
325+
if txInBlock.Hash() == vLog.TxHash {
326+
tx = txInBlock
327+
found = true
328+
break
329+
}
330+
}
331+
if !found {
332+
return nil, fmt.Errorf("transaction not found in the block, tx hash: %v, block number: %v, block hash: %v", vLog.TxHash.Hex(), vLog.BlockNumber, vLog.BlockHash.Hex())
333+
}
317334
}
318335

319336
return s.decodeChunkBlockRanges(tx.Data())
@@ -323,17 +340,17 @@ func (s *RollupSyncService) getChunkRanges(batchIndex uint64, vLog *types.Log) (
323340
func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.ChunkBlockRange, error) {
324341
const methodIDLength = 4
325342
if len(txData) < methodIDLength {
326-
return nil, fmt.Errorf("transaction data is too short")
343+
return nil, fmt.Errorf("transaction data is too short, length of tx data: %v, minimum length required: %v", len(txData), methodIDLength)
327344
}
328345

329346
method, err := s.scrollChainABI.MethodById(txData[:methodIDLength])
330347
if err != nil {
331-
return nil, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:4], err)
348+
return nil, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:methodIDLength], err)
332349
}
333350

334351
values, err := method.Inputs.Unpack(txData[methodIDLength:])
335352
if err != nil {
336-
return nil, fmt.Errorf("failed to unpack transaction data using ABI: %v", err)
353+
return nil, fmt.Errorf("failed to unpack transaction data using ABI, tx data: %v, err: %w", txData, err)
337354
}
338355

339356
type commitBatchArgs struct {
@@ -345,11 +362,11 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun
345362
var args commitBatchArgs
346363
err = method.Inputs.Copy(&args, values)
347364
if err != nil {
348-
return nil, fmt.Errorf("failed to decode calldata into commitBatch args, err: %w", err)
365+
return nil, fmt.Errorf("failed to decode calldata into commitBatch args, values: %+v, err: %w", values, err)
349366
}
350367

351368
if args.Version != batchHeaderVersion {
352-
return nil, fmt.Errorf("unexpected batch version, expected: %d, got: %v", batchHeaderVersion, args.Version)
369+
return nil, fmt.Errorf("unexpected batch version, expected: %v, got: %v", batchHeaderVersion, args.Version)
353370
}
354371

355372
return DecodeChunkBlockRanges(args.Chunks)
@@ -360,18 +377,18 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun
360377
// It returns the number of the end block, a finalized batch meta data, and an error if any.
361378
func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*Chunk) (uint64, *rawdb.FinalizedBatchMeta, error) {
362379
if len(chunks) == 0 {
363-
return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0")
380+
return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64())
364381
}
365382

366383
startChunk := chunks[0]
367384
if len(startChunk.Blocks) == 0 {
368-
return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0")
385+
return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", event.BatchIndex.Uint64())
369386
}
370387
startBlock := startChunk.Blocks[0]
371388

372389
endChunk := chunks[len(chunks)-1]
373390
if len(endChunk.Blocks) == 0 {
374-
return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0")
391+
return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", event.BatchIndex.Uint64())
375392
}
376393
endBlock := endChunk.Blocks[len(endChunk.Blocks)-1]
377394

@@ -392,15 +409,18 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized
392409
// Note: All params for NewBatchHeader are calculated locally based on the block data.
393410
batchHeader, err := NewBatchHeader(batchHeaderVersion, event.BatchIndex.Uint64(), parentBatchMeta.TotalL1MessagePopped, parentBatchMeta.BatchHash, chunks)
394411
if err != nil {
395-
return 0, nil, fmt.Errorf("failed to construct batch header, err: %w", err)
412+
return 0, nil, fmt.Errorf("failed to construct batch header, batch index: %v, err: %w", event.BatchIndex.Uint64(), err)
396413
}
397414

398415
// Note: If the batch headers match, this ensures the consistency of blocks and transactions
399416
// (including skipped transactions) between L1 and L2.
400417
localBatchHash := batchHeader.Hash()
401418
if localBatchHash != event.BatchHash {
402419
log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex())
403-
chunksJson, _ := json.Marshal(chunks)
420+
chunksJson, err := json.Marshal(chunks)
421+
if err != nil {
422+
log.Error("marshal chunks failed", "err", err)
423+
}
404424
log.Error("Chunks", "chunks", string(chunksJson))
405425
syscall.Kill(os.Getpid(), syscall.SIGTERM)
406426
return 0, nil, fmt.Errorf("batch hash mismatch")

rollup/sync_service/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ type EthClient interface {
1818
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
1919
SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
2020
TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error)
21+
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
2122
}

0 commit comments

Comments
 (0)