From badde3cba559d35c0bff434c5b916e42ec91e0a1 Mon Sep 17 00:00:00 2001 From: colin <102356659+colinlyguo@users.noreply.github.com> Date: Sun, 8 Oct 2023 19:39:17 +0800 Subject: [PATCH] fix(rollup-relayer): better handle commit batch revert (#981) Co-authored-by: colinlyguo Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> --- common/version/version.go | 2 +- rollup/internal/controller/relayer/l2_relayer.go | 15 +++++++++++++-- rollup/internal/orm/batch.go | 8 ++++---- rollup/internal/orm/orm_test.go | 7 +++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/common/version/version.go b/common/version/version.go index 43e2510125..c963690c15 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.3.30" +var tag = "v4.3.31" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go index d1600b55c1..114c8c973b 100644 --- a/rollup/internal/controller/relayer/l2_relayer.go +++ b/rollup/internal/controller/relayer/l2_relayer.go @@ -307,12 +307,12 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() { // ProcessPendingBatches processes the pending batches by sending commitBatch transactions to layer 1. func (r *Layer2Relayer) ProcessPendingBatches() { // get pending batches from database in ascending order by their index. - pendingBatches, err := r.batchOrm.GetPendingBatches(r.ctx, 5) + batches, err := r.batchOrm.GetFailedAndPendingBatches(r.ctx, 5) if err != nil { log.Error("Failed to fetch pending L2 batches", "err", err) return } - for _, batch := range pendingBatches { + for _, batch := range batches { r.metrics.rollupL2RelayerProcessPendingBatchTotal.Inc() // get current header and parent header. currentBatchHeader, err := types.DecodeBatchHeader(batch.BatchHeader) @@ -327,6 +327,12 @@ func (r *Layer2Relayer) ProcessPendingBatches() { log.Error("Failed to get parent batch header", "index", batch.Index-1, "error", err) return } + + if types.RollupStatus(parentBatch.RollupStatus) == types.RollupCommitFailed { + log.Error("Previous batch commit failed, halting further committing", + "index", parentBatch.Index, "tx hash", parentBatch.CommitTxHash) + return + } } // get the chunks for the batch @@ -371,6 +377,11 @@ func (r *Layer2Relayer) ProcessPendingBatches() { // send transaction txID := batch.Hash + "-commit" fallbackGasLimit := uint64(float64(batch.TotalL1CommitGas) * r.cfg.L1CommitGasLimitMultiplier) + if types.RollupStatus(batch.RollupStatus) == types.RollupCommitFailed { + // use eth_estimateGas if this batch has been committed failed. + fallbackGasLimit = 0 + log.Warn("Batch commit previously failed, using eth_estimateGas for the re-submission", "hash", batch.Hash) + } txHash, err := r.commitSender.SendTransaction(txID, &r.cfg.RollupContractAddress, big.NewInt(0), calldata, fallbackGasLimit) if err != nil { log.Error( diff --git a/rollup/internal/orm/batch.go b/rollup/internal/orm/batch.go index 0ade60b5c6..64877163d3 100644 --- a/rollup/internal/orm/batch.go +++ b/rollup/internal/orm/batch.go @@ -192,22 +192,22 @@ func (o *Batch) GetRollupStatusByHashList(ctx context.Context, hashes []string) return statuses, nil } -// GetPendingBatches retrieves pending batches up to the specified limit. +// GetFailedAndPendingBatches retrieves batches with failed or pending status up to the specified limit. // The returned batches are sorted in ascending order by their index. -func (o *Batch) GetPendingBatches(ctx context.Context, limit int) ([]*Batch, error) { +func (o *Batch) GetFailedAndPendingBatches(ctx context.Context, limit int) ([]*Batch, error) { if limit <= 0 { return nil, errors.New("limit must be greater than zero") } db := o.db.WithContext(ctx) db = db.Model(&Batch{}) - db = db.Where("rollup_status = ?", types.RollupPending) + db = db.Where("rollup_status = ? OR rollup_status = ?", types.RollupCommitFailed, types.RollupPending) db = db.Order("index ASC") db = db.Limit(limit) var batches []*Batch if err := db.Find(&batches).Error; err != nil { - return nil, fmt.Errorf("Batch.GetPendingBatches error: %w", err) + return nil, fmt.Errorf("Batch.GetFailedAndPendingBatches error: %w", err) } return batches, nil } diff --git a/rollup/internal/orm/orm_test.go b/rollup/internal/orm/orm_test.go index 1010a531f5..bdbde4f884 100644 --- a/rollup/internal/orm/orm_test.go +++ b/rollup/internal/orm/orm_test.go @@ -258,14 +258,17 @@ func TestBatchOrm(t *testing.T) { assert.NoError(t, err) assert.Equal(t, uint64(2), count) - pendingBatches, err := batchOrm.GetPendingBatches(context.Background(), 100) + err = batchOrm.UpdateRollupStatus(context.Background(), batchHash1, types.RollupCommitFailed) + assert.NoError(t, err) + + pendingBatches, err := batchOrm.GetFailedAndPendingBatches(context.Background(), 100) assert.NoError(t, err) assert.Equal(t, 2, len(pendingBatches)) rollupStatus, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batchHash1, batchHash2}) assert.NoError(t, err) assert.Equal(t, 2, len(rollupStatus)) - assert.Equal(t, types.RollupPending, rollupStatus[0]) + assert.Equal(t, types.RollupCommitFailed, rollupStatus[0]) assert.Equal(t, types.RollupPending, rollupStatus[1]) err = batchOrm.UpdateProvingStatus(context.Background(), batchHash2, types.ProvingTaskVerified)