From f4663fd2492b803a72d21b16c43b0312a745e5a5 Mon Sep 17 00:00:00 2001 From: colin <102356659+colinlyguo@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:00:16 +0800 Subject: [PATCH] feat(rollup-relayer): add number of blocks per chunk limit (#880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colinlyguo Co-authored-by: Péter Garamvölgyi Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Co-authored-by: HAOYUatHZ --- common/version/version.go | 2 +- rollup/conf/config.json | 3 +- rollup/internal/config/l2.go | 1 + .../controller/watcher/batch_proposer.go | 28 ++++++++++------- .../controller/watcher/batch_proposer_test.go | 1 + .../controller/watcher/chunk_proposer.go | 30 ++++++++++++------- .../controller/watcher/chunk_proposer_test.go | 2 ++ rollup/tests/rollup_test.go | 1 + 8 files changed, 44 insertions(+), 24 deletions(-) diff --git a/common/version/version.go b/common/version/version.go index 14ce89d967..083d28abe0 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.2.19" +var tag = "v4.2.20" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/rollup/conf/config.json b/rollup/conf/config.json index b34cf6b3d2..74679ece3d 100644 --- a/rollup/conf/config.json +++ b/rollup/conf/config.json @@ -65,7 +65,8 @@ "gas_cost_increase_multiplier": 1.2 }, "chunk_proposer_config": { - "max_tx_num_per_chunk": 1123, + "max_block_num_per_chunk": 100, + "max_tx_num_per_chunk": 100, "max_l1_commit_gas_per_chunk": 11234567, "max_l1_commit_calldata_size_per_chunk": 112345, "chunk_timeout_sec": 300, diff --git a/rollup/internal/config/l2.go b/rollup/internal/config/l2.go index 099ee8e26d..8996b88ee1 100644 --- a/rollup/internal/config/l2.go +++ b/rollup/internal/config/l2.go @@ -28,6 +28,7 @@ type L2Config struct { // ChunkProposerConfig loads chunk_proposer configuration items. type ChunkProposerConfig struct { + MaxBlockNumPerChunk uint64 `json:"max_block_num_per_chunk"` MaxTxNumPerChunk uint64 `json:"max_tx_num_per_chunk"` MaxL1CommitGasPerChunk uint64 `json:"max_l1_commit_gas_per_chunk"` MaxL1CommitCalldataSizePerChunk uint64 `json:"max_l1_commit_calldata_size_per_chunk"` diff --git a/rollup/internal/controller/watcher/batch_proposer.go b/rollup/internal/controller/watcher/batch_proposer.go index e1ccc5b7b3..7b99c2c4c8 100644 --- a/rollup/internal/controller/watcher/batch_proposer.go +++ b/rollup/internal/controller/watcher/batch_proposer.go @@ -154,7 +154,8 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er return nil, nil, err } - dbChunks, err := p.chunkOrm.GetChunksGEIndex(p.ctx, unbatchedChunkIndex, int(p.maxChunkNumPerBatch)+1) + // select at most p.maxChunkNumPerBatch chunks + dbChunks, err := p.chunkOrm.GetChunksGEIndex(p.ctx, unbatchedChunkIndex, int(p.maxChunkNumPerBatch)) if err != nil { return nil, nil, err } @@ -207,8 +208,7 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er totalL1CommitGas += types.CalldataNonZeroByteGas * (32 * (totalL1MessagePopped + 255) / 256) totalL1CommitGas += types.GetKeccak256Gas(89 + 32*(totalL1MessagePopped+255)/256) totalOverEstimateL1CommitGas := uint64(p.gasCostIncreaseMultiplier * float64(totalL1CommitGas)) - if totalChunks > p.maxChunkNumPerBatch || - totalL1CommitCalldataSize > p.maxL1CommitCalldataSizePerBatch || + if totalL1CommitCalldataSize > p.maxL1CommitCalldataSizePerBatch || totalOverEstimateL1CommitGas > p.maxL1CommitGasPerBatch { // Check if the first chunk breaks hard limits. // If so, it indicates there are bugs in chunk-proposer, manual fix is needed. @@ -234,8 +234,6 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er } log.Debug("breaking limit condition in batching", - "currentTotalChunks", totalChunks, - "maxChunkNumPerBatch", p.maxChunkNumPerBatch, "currentL1CommitCalldataSize", totalL1CommitCalldataSize, "maxL1CommitCalldataSizePerBatch", p.maxL1CommitCalldataSizePerBatch, "currentOverEstimateL1CommitGas", totalOverEstimateL1CommitGas, @@ -249,12 +247,20 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, *types.BatchMeta, er } currentTimeSec := uint64(time.Now().Unix()) - if dbChunks[0].StartBlockTime+p.batchTimeoutSec < currentTimeSec { - log.Warn("first block timeout", - "start block number", dbChunks[0].StartBlockNumber, - "first block timestamp", dbChunks[0].StartBlockTime, - "chunk outdated time threshold", currentTimeSec, - ) + if dbChunks[0].StartBlockTime+p.batchTimeoutSec < currentTimeSec || + totalChunks == p.maxChunkNumPerBatch { + if dbChunks[0].StartBlockTime+p.batchTimeoutSec < currentTimeSec { + log.Warn("first block timeout", + "start block number", dbChunks[0].StartBlockNumber, + "start block timestamp", dbChunks[0].StartBlockTime, + "current time", currentTimeSec, + ) + } else { + log.Info("reached maximum number of chunks in batch", + "chunk count", totalChunks, + ) + } + batchMeta.TotalL1CommitGas = totalL1CommitGas batchMeta.TotalL1CommitCalldataSize = totalL1CommitCalldataSize p.batchFirstBlockTimeoutReached.Inc() diff --git a/rollup/internal/controller/watcher/batch_proposer_test.go b/rollup/internal/controller/watcher/batch_proposer_test.go index 69467f11a0..a8dd81aede 100644 --- a/rollup/internal/controller/watcher/batch_proposer_test.go +++ b/rollup/internal/controller/watcher/batch_proposer_test.go @@ -23,6 +23,7 @@ func testBatchProposer(t *testing.T) { assert.NoError(t, err) cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ + MaxBlockNumPerChunk: 100, MaxTxNumPerChunk: 10000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000, diff --git a/rollup/internal/controller/watcher/chunk_proposer.go b/rollup/internal/controller/watcher/chunk_proposer.go index 42a45253fc..6c9be6fd36 100644 --- a/rollup/internal/controller/watcher/chunk_proposer.go +++ b/rollup/internal/controller/watcher/chunk_proposer.go @@ -18,10 +18,6 @@ import ( "scroll-tech/rollup/internal/orm" ) -// maxNumBlockPerChunk is the maximum number of blocks we allow per chunk. -// Normally we will pack much fewer blocks because of other limits. -const maxNumBlockPerChunk int = 100 - // chunkRowConsumption is map(sub-circuit name => sub-circuit row count) type chunkRowConsumption map[string]uint64 @@ -55,6 +51,7 @@ type ChunkProposer struct { chunkOrm *orm.Chunk l2BlockOrm *orm.L2Block + maxBlockNumPerChunk uint64 maxTxNumPerChunk uint64 maxL1CommitGasPerChunk uint64 maxL1CommitCalldataSizePerChunk uint64 @@ -90,6 +87,7 @@ func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, db * db: db, chunkOrm: orm.NewChunk(db), l2BlockOrm: orm.NewL2Block(db), + maxBlockNumPerChunk: cfg.MaxBlockNumPerChunk, maxTxNumPerChunk: cfg.MaxTxNumPerChunk, maxL1CommitGasPerChunk: cfg.MaxL1CommitGasPerChunk, maxL1CommitCalldataSizePerChunk: cfg.MaxL1CommitCalldataSizePerChunk, @@ -191,7 +189,8 @@ func (p *ChunkProposer) proposeChunk() (*types.Chunk, error) { return nil, err } - blocks, err := p.l2BlockOrm.GetL2WrappedBlocksGEHeight(p.ctx, unchunkedBlockHeight, maxNumBlockPerChunk) + // select at most p.maxBlockNumPerChunk blocks + blocks, err := p.l2BlockOrm.GetL2WrappedBlocksGEHeight(p.ctx, unchunkedBlockHeight, int(p.maxBlockNumPerChunk)) if err != nil { return nil, err } @@ -293,12 +292,21 @@ func (p *ChunkProposer) proposeChunk() (*types.Chunk, error) { } currentTimeSec := uint64(time.Now().Unix()) - if blocks[0].Header.Time+p.chunkTimeoutSec < currentTimeSec { - log.Warn("first block timeout", - "block number", blocks[0].Header.Number, - "block timestamp", blocks[0].Header.Time, - "block outdated time threshold", currentTimeSec, - ) + if chunk.Blocks[0].Header.Time+p.chunkTimeoutSec < currentTimeSec || + uint64(len(chunk.Blocks)) == p.maxBlockNumPerChunk { + if chunk.Blocks[0].Header.Time+p.chunkTimeoutSec < currentTimeSec { + log.Warn("first block timeout", + "block number", chunk.Blocks[0].Header.Number, + "block timestamp", chunk.Blocks[0].Header.Time, + "current time", currentTimeSec, + ) + } else { + log.Info("reached maximum number of blocks in chunk", + "start block number", chunk.Blocks[0].Header.Number, + "block count", len(chunk.Blocks), + ) + } + p.chunkFirstBlockTimeoutReached.Inc() p.chunkTxNum.Set(float64(totalTxNum)) p.chunkEstimateL1CommitGas.Set(float64(totalL1CommitGas)) diff --git a/rollup/internal/controller/watcher/chunk_proposer_test.go b/rollup/internal/controller/watcher/chunk_proposer_test.go index 6899d07e4b..1fff539e72 100644 --- a/rollup/internal/controller/watcher/chunk_proposer_test.go +++ b/rollup/internal/controller/watcher/chunk_proposer_test.go @@ -23,6 +23,7 @@ func testChunkProposer(t *testing.T) { assert.NoError(t, err) cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ + MaxBlockNumPerChunk: 100, MaxTxNumPerChunk: 10000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000, @@ -53,6 +54,7 @@ func testChunkProposerRowConsumption(t *testing.T) { assert.NoError(t, err) cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ + MaxBlockNumPerChunk: 100, MaxTxNumPerChunk: 10000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000, diff --git a/rollup/tests/rollup_test.go b/rollup/tests/rollup_test.go index 62a62b5f3c..5eae9d86b1 100644 --- a/rollup/tests/rollup_test.go +++ b/rollup/tests/rollup_test.go @@ -57,6 +57,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) { assert.NoError(t, err) cp := watcher.NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ + MaxBlockNumPerChunk: 100, MaxTxNumPerChunk: 10000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000,