diff --git a/core/rawdb/accessors_rollup_event.go b/core/rawdb/accessors_rollup_event.go index a3575df44a..796e60628a 100644 --- a/core/rawdb/accessors_rollup_event.go +++ b/core/rawdb/accessors_rollup_event.go @@ -28,7 +28,7 @@ type FinalizedBatchMeta struct { func WriteRollupEventSyncedL1BlockNumber(db ethdb.KeyValueWriter, l1BlockNumber uint64) { value := big.NewInt(0).SetUint64(l1BlockNumber).Bytes() if err := db.Put(rollupEventSyncedL1BlockNumberKey, value); err != nil { - log.Crit("failed to store rollup event synced L1 block number for rollup event", "err", err) + log.Crit("failed to store rollup event synced L1 block number for rollup event", "L1 block number", l1BlockNumber, "value", value, "err", err) } } @@ -44,7 +44,7 @@ func ReadRollupEventSyncedL1BlockNumber(db ethdb.Reader) *uint64 { number := new(big.Int).SetBytes(data) if !number.IsUint64() { - log.Crit("unexpected rollup event synced L1 block number in database", "number", number) + log.Crit("unexpected rollup event synced L1 block number in database", "data", data, "number", number) } rollupEventSyncedL1BlockNumber := number.Uint64() @@ -54,12 +54,12 @@ func ReadRollupEventSyncedL1BlockNumber(db ethdb.Reader) *uint64 { // WriteBatchChunkRanges writes the block ranges for each chunk within a batch to the database. // It serializes the chunk ranges using RLP and stores them under a key derived from the batch index. func WriteBatchChunkRanges(db ethdb.KeyValueWriter, batchIndex uint64, chunkBlockRanges []*ChunkBlockRange) { - bytes, err := rlp.EncodeToBytes(chunkBlockRanges) + value, err := rlp.EncodeToBytes(chunkBlockRanges) if err != nil { log.Crit("failed to RLP encode batch chunk ranges", "batch index", batchIndex, "err", err) } - if err := db.Put(batchChunkRangesKey(batchIndex), bytes); err != nil { - log.Crit("failed to store batch chunk ranges", "batch index", batchIndex, "err", err) + if err := db.Put(batchChunkRangesKey(batchIndex), value); err != nil { + log.Crit("failed to store batch chunk ranges", "batch index", batchIndex, "value", value, "err", err) } } @@ -92,12 +92,12 @@ func ReadBatchChunkRanges(db ethdb.Reader, batchIndex uint64) []*ChunkBlockRange // WriteFinalizedBatchMeta stores the metadata of a finalized batch in the database. func WriteFinalizedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, finalizedBatchMeta *FinalizedBatchMeta) { var err error - bytes, err := rlp.EncodeToBytes(finalizedBatchMeta) + value, err := rlp.EncodeToBytes(finalizedBatchMeta) if err != nil { - log.Crit("failed to RLP encode batch metadata", "batch index", batchIndex, "err", err) + log.Crit("failed to RLP encode batch metadata", "batch index", batchIndex, "finalized batch meta", finalizedBatchMeta, "err", err) } - if err := db.Put(batchMetaKey(batchIndex), bytes); err != nil { - log.Crit("failed to store batch metadata", "batch index", batchIndex, "err", err) + if err := db.Put(batchMetaKey(batchIndex), value); err != nil { + log.Crit("failed to store batch metadata", "batch index", batchIndex, "value", value, "err", err) } } @@ -108,7 +108,7 @@ func ReadFinalizedBatchMeta(db ethdb.Reader, batchIndex uint64) *FinalizedBatchM return nil } if err != nil { - log.Crit("failed to read finalized batch metadata from database", "err", err) + log.Crit("failed to read finalized batch metadata from database", "batch index", batchIndex, "err", err) } fbm := new(FinalizedBatchMeta) @@ -122,7 +122,7 @@ func ReadFinalizedBatchMeta(db ethdb.Reader, batchIndex uint64) *FinalizedBatchM func WriteFinalizedL2BlockNumber(db ethdb.KeyValueWriter, l2BlockNumber uint64) { value := big.NewInt(0).SetUint64(l2BlockNumber).Bytes() if err := db.Put(finalizedL2BlockNumberKey, value); err != nil { - log.Crit("failed to store finalized L2 block number for rollup event", "err", err) + log.Crit("failed to store finalized L2 block number for rollup event", "L2 block number", l2BlockNumber, "value", value, "err", err) } } @@ -133,12 +133,12 @@ func ReadFinalizedL2BlockNumber(db ethdb.Reader) *uint64 { return nil } if err != nil { - log.Crit("failed to read finalized L2 block number from database", "err", err) + log.Crit("failed to read finalized L2 block number from database", "key", finalizedL2BlockNumberKey, "err", err) } number := new(big.Int).SetBytes(data) if !number.IsUint64() { - log.Crit("unexpected finalized L2 block number in database", "number", number) + log.Crit("unexpected finalized L2 block number in database", "data", data, "number", number) } finalizedL2BlockNumber := number.Uint64() diff --git a/params/version.go b/params/version.go index 9604c504db..56de5b79e2 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 5 // Major version component of the current release VersionMinor = 1 // Minor version component of the current release - VersionPatch = 6 // Patch version component of the current release + VersionPatch = 7 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) diff --git a/rollup/rollup_sync_service/chunk.go b/rollup/rollup_sync_service/chunk.go index 6df318d358..dff2eca7e6 100644 --- a/rollup/rollup_sync_service/chunk.go +++ b/rollup/rollup_sync_service/chunk.go @@ -132,7 +132,7 @@ func DecodeChunkBlockRanges(chunks [][]byte) ([]*rawdb.ChunkBlockRange, error) { numBlocks := int(chunk[0]) if len(chunk) < 1+numBlocks*blockContextByteSize { - return nil, fmt.Errorf("chunk size doesn't match with numBlocks") + return nil, fmt.Errorf("chunk size doesn't match with numBlocks, byte length of chunk: %v, expected length: %v", len(chunk), 1+numBlocks*blockContextByteSize) } blockContexts := make([]*BlockContext, numBlocks) diff --git a/rollup/rollup_sync_service/l1client_test.go b/rollup/rollup_sync_service/l1client_test.go index 2ac6ee6e66..79c82c8a31 100644 --- a/rollup/rollup_sync_service/l1client_test.go +++ b/rollup/rollup_sync_service/l1client_test.go @@ -68,3 +68,7 @@ func (m *mockEthClient) TransactionByHash(ctx context.Context, txHash common.Has } return &tx, false, nil } + +func (m *mockEthClient) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return nil, nil +} diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index b6d0f653f0..453f0d9bd3 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -196,7 +196,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB chunkBlockRanges, err := s.getChunkRanges(batchIndex, &vLog) if err != nil { - return fmt.Errorf("failed to get chunk ranges, err: %w", err) + return fmt.Errorf("failed to get chunk ranges, batch index: %v, err: %w", batchIndex, err) } rawdb.WriteBatchChunkRanges(s.db, batchIndex, chunkBlockRanges) @@ -311,9 +311,26 @@ func (s *RollupSyncService) getChunkRanges(batchIndex uint64, vLog *types.Log) ( return []*rawdb.ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 0}}, nil } - tx, _, err := s.client.client.TransactionByHash(context.Background(), vLog.TxHash) + tx, _, err := s.client.client.TransactionByHash(s.ctx, vLog.TxHash) if err != nil { - return nil, fmt.Errorf("failed to get transaction, err: %w", err) + log.Debug("failed to get transaction by hash, probably an unindexed transaction, fetching the whole block to get the transaction", + "tx hash", vLog.TxHash.Hex(), "block number", vLog.BlockNumber, "block hash", vLog.BlockHash.Hex(), "err", err) + block, err := s.client.client.BlockByHash(s.ctx, vLog.BlockHash) + if err != nil { + return nil, fmt.Errorf("failed to get block by hash, block number: %v, block hash: %v, err: %w", vLog.BlockNumber, vLog.BlockHash.Hex(), err) + } + + found := false + for _, txInBlock := range block.Transactions() { + if txInBlock.Hash() == vLog.TxHash { + tx = txInBlock + found = true + break + } + } + if !found { + 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()) + } } return s.decodeChunkBlockRanges(tx.Data()) @@ -323,17 +340,17 @@ func (s *RollupSyncService) getChunkRanges(batchIndex uint64, vLog *types.Log) ( func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.ChunkBlockRange, error) { const methodIDLength = 4 if len(txData) < methodIDLength { - return nil, fmt.Errorf("transaction data is too short") + return nil, fmt.Errorf("transaction data is too short, length of tx data: %v, minimum length required: %v", len(txData), methodIDLength) } method, err := s.scrollChainABI.MethodById(txData[:methodIDLength]) if err != nil { - return nil, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:4], err) + return nil, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:methodIDLength], err) } values, err := method.Inputs.Unpack(txData[methodIDLength:]) if err != nil { - return nil, fmt.Errorf("failed to unpack transaction data using ABI: %v", err) + return nil, fmt.Errorf("failed to unpack transaction data using ABI, tx data: %v, err: %w", txData, err) } type commitBatchArgs struct { @@ -345,11 +362,11 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun var args commitBatchArgs err = method.Inputs.Copy(&args, values) if err != nil { - return nil, fmt.Errorf("failed to decode calldata into commitBatch args, err: %w", err) + return nil, fmt.Errorf("failed to decode calldata into commitBatch args, values: %+v, err: %w", values, err) } if args.Version != batchHeaderVersion { - return nil, fmt.Errorf("unexpected batch version, expected: %d, got: %v", batchHeaderVersion, args.Version) + return nil, fmt.Errorf("unexpected batch version, expected: %v, got: %v", batchHeaderVersion, args.Version) } return DecodeChunkBlockRanges(args.Chunks) @@ -360,18 +377,18 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // It returns the number of the end block, a finalized batch meta data, and an error if any. func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*Chunk) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { - return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0") + return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64()) } startChunk := chunks[0] if len(startChunk.Blocks) == 0 { - return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0") + return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", event.BatchIndex.Uint64()) } startBlock := startChunk.Blocks[0] endChunk := chunks[len(chunks)-1] if len(endChunk.Blocks) == 0 { - return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0") + return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", event.BatchIndex.Uint64()) } endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] @@ -392,7 +409,7 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized // Note: All params for NewBatchHeader are calculated locally based on the block data. batchHeader, err := NewBatchHeader(batchHeaderVersion, event.BatchIndex.Uint64(), parentBatchMeta.TotalL1MessagePopped, parentBatchMeta.BatchHash, chunks) if err != nil { - return 0, nil, fmt.Errorf("failed to construct batch header, err: %w", err) + return 0, nil, fmt.Errorf("failed to construct batch header, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) } // Note: If the batch headers match, this ensures the consistency of blocks and transactions @@ -400,7 +417,10 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized localBatchHash := batchHeader.Hash() if localBatchHash != event.BatchHash { 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()) - chunksJson, _ := json.Marshal(chunks) + chunksJson, err := json.Marshal(chunks) + if err != nil { + log.Error("marshal chunks failed", "err", err) + } log.Error("Chunks", "chunks", string(chunksJson)) syscall.Kill(os.Getpid(), syscall.SIGTERM) return 0, nil, fmt.Errorf("batch hash mismatch") diff --git a/rollup/sync_service/types.go b/rollup/sync_service/types.go index 0bc062772a..3429ec1bb7 100644 --- a/rollup/sync_service/types.go +++ b/rollup/sync_service/types.go @@ -18,4 +18,5 @@ type EthClient interface { HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) }