diff --git a/rollup/cmd/rollup_relayer/app/app.go b/rollup/cmd/rollup_relayer/app/app.go index 0e7c617ce1..0ea0f676bf 100644 --- a/rollup/cmd/rollup_relayer/app/app.go +++ b/rollup/cmd/rollup_relayer/app/app.go @@ -89,7 +89,7 @@ func action(ctx *cli.Context) error { log.Crit("failed to create chunkProposer", "config file", cfgFile, "error", err) } - batchProposer := watcher.NewBatchProposer(subCtx, cfg.L2Config.BatchProposerConfig, db, registry) + batchProposer := watcher.NewBatchProposer(subCtx, cfg.L2Config.BatchProposerConfig, network.GenesisConfig(), db, registry) if err != nil { log.Crit("failed to create batchProposer", "config file", cfgFile, "error", err) } diff --git a/rollup/internal/controller/watcher/batch_proposer.go b/rollup/internal/controller/watcher/batch_proposer.go index 0c3b0ba1d6..d07ec1ff55 100644 --- a/rollup/internal/controller/watcher/batch_proposer.go +++ b/rollup/internal/controller/watcher/batch_proposer.go @@ -3,13 +3,16 @@ package watcher import ( "context" "fmt" + "slices" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/scroll-tech/go-ethereum/log" + "github.com/scroll-tech/go-ethereum/params" "gorm.io/gorm" + "scroll-tech/common/network" "scroll-tech/common/types" "scroll-tech/rollup/internal/config" @@ -30,6 +33,7 @@ type BatchProposer struct { maxL1CommitCalldataSizePerBatch uint32 batchTimeoutSec uint64 gasCostIncreaseMultiplier float64 + forkHeights []uint64 batchProposerCircleTotal prometheus.Counter proposeBatchFailureTotal prometheus.Counter @@ -43,13 +47,15 @@ type BatchProposer struct { } // NewBatchProposer creates a new BatchProposer instance. -func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, db *gorm.DB, reg prometheus.Registerer) *BatchProposer { +func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, chainCfg *params.ChainConfig, db *gorm.DB, reg prometheus.Registerer) *BatchProposer { + forkHeights := network.CollectSortedForkHeights(chainCfg) log.Debug("new batch proposer", "maxChunkNumPerBatch", cfg.MaxChunkNumPerBatch, "maxL1CommitGasPerBatch", cfg.MaxL1CommitGasPerBatch, "maxL1CommitCalldataSizePerBatch", cfg.MaxL1CommitCalldataSizePerBatch, "batchTimeoutSec", cfg.BatchTimeoutSec, - "gasCostIncreaseMultiplier", cfg.GasCostIncreaseMultiplier) + "gasCostIncreaseMultiplier", cfg.GasCostIncreaseMultiplier, + "forkHeights", forkHeights) return &BatchProposer{ ctx: ctx, @@ -62,6 +68,7 @@ func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, db * maxL1CommitCalldataSizePerBatch: cfg.MaxL1CommitCalldataSizePerBatch, batchTimeoutSec: cfg.BatchTimeoutSec, gasCostIncreaseMultiplier: cfg.GasCostIncreaseMultiplier, + forkHeights: forkHeights, batchProposerCircleTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{ Name: "rollup_propose_batch_circle_total", @@ -193,6 +200,18 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er totalL1CommitGas += types.CalldataNonZeroByteGas * uint64(len(parentBatch.BatchHeader)) // parent batch header in calldata } + maxChunksThisBatch := p.maxChunkNumPerBatch + for i, chunk := range dbChunks { + // if a chunk is starting at a fork boundary, only consider earlier chunks + if i != 0 && slices.Index(p.forkHeights, chunk.StartBlockNumber) != -1 { + dbChunks = dbChunks[:i] + if uint64(len(dbChunks)) < maxChunksThisBatch { + maxChunksThisBatch = uint64(len(dbChunks)) + } + break + } + } + for i, chunk := range dbChunks { // metric values batchMeta.TotalL1CommitGas = totalL1CommitGas @@ -253,7 +272,7 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er currentTimeSec := uint64(time.Now().Unix()) if dbChunks[0].StartBlockTime+p.batchTimeoutSec < currentTimeSec || - totalChunks == p.maxChunkNumPerBatch { + totalChunks == maxChunksThisBatch { if dbChunks[0].StartBlockTime+p.batchTimeoutSec < currentTimeSec { log.Warn("first block timeout", "start block number", dbChunks[0].StartBlockNumber, diff --git a/rollup/internal/controller/watcher/batch_proposer_test.go b/rollup/internal/controller/watcher/batch_proposer_test.go index 49c05ed193..ccbbb69ffd 100644 --- a/rollup/internal/controller/watcher/batch_proposer_test.go +++ b/rollup/internal/controller/watcher/batch_proposer_test.go @@ -2,6 +2,7 @@ package watcher import ( "context" + "math/big" "testing" "github.com/scroll-tech/go-ethereum/params" @@ -21,6 +22,7 @@ func testBatchProposerLimits(t *testing.T) { maxL1CommitGas uint64 maxL1CommitCalldataSize uint32 batchTimeoutSec uint64 + forkBlock *big.Int expectedBatchesLen int expectedChunksInFirstBatch uint64 // only be checked when expectedBatchesLen > 0 }{ @@ -84,6 +86,16 @@ func testBatchProposerLimits(t *testing.T) { expectedBatchesLen: 1, expectedChunksInFirstBatch: 1, }, + { + name: "ForkBlockReached", + maxChunkNum: 10, + maxL1CommitGas: 50000000000, + maxL1CommitCalldataSize: 1000000, + batchTimeoutSec: 1000000000000, + expectedBatchesLen: 1, + expectedChunksInFirstBatch: 1, + forkBlock: big.NewInt(3), + }, } for _, tt := range tests { @@ -103,7 +115,9 @@ func testBatchProposerLimits(t *testing.T) { MaxRowConsumptionPerChunk: 1000000, ChunkTimeoutSec: 300, GasCostIncreaseMultiplier: 1.2, - }, ¶ms.ChainConfig{}, db, nil) + }, ¶ms.ChainConfig{ + HomesteadBlock: tt.forkBlock, + }, db, nil) cp.TryProposeChunk() // chunk1 contains block1 cp.TryProposeChunk() // chunk2 contains block2 @@ -121,6 +135,8 @@ func testBatchProposerLimits(t *testing.T) { MaxL1CommitCalldataSizePerBatch: tt.maxL1CommitCalldataSize, BatchTimeoutSec: tt.batchTimeoutSec, GasCostIncreaseMultiplier: 1.2, + }, ¶ms.ChainConfig{ + HomesteadBlock: tt.forkBlock, }, db, nil) bp.TryProposeBatch() @@ -180,7 +196,7 @@ func testBatchCommitGasAndCalldataSizeEstimation(t *testing.T) { MaxL1CommitCalldataSizePerBatch: 1000000, BatchTimeoutSec: 0, GasCostIncreaseMultiplier: 1.2, - }, db, nil) + }, ¶ms.ChainConfig{}, db, nil) bp.TryProposeBatch() batchOrm := orm.NewBatch(db) diff --git a/rollup/tests/rollup_test.go b/rollup/tests/rollup_test.go index 3b5ee437ee..92ddffd3dc 100644 --- a/rollup/tests/rollup_test.go +++ b/rollup/tests/rollup_test.go @@ -109,7 +109,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) { MaxL1CommitGasPerBatch: 50000000000, MaxL1CommitCalldataSizePerBatch: 1000000, BatchTimeoutSec: 300, - }, db, nil) + }, ¶ms.ChainConfig{}, db, nil) bp.TryProposeBatch() l2Relayer.ProcessPendingBatches()