diff --git a/common/version/version.go b/common/version/version.go index 62056e6a93..db847f7e86 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.4.96" +var tag = "v4.4.97" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/rollup/cmd/rollup_relayer/app/app.go b/rollup/cmd/rollup_relayer/app/app.go index 7e28235409..487ad2870b 100644 --- a/rollup/cmd/rollup_relayer/app/app.go +++ b/rollup/cmd/rollup_relayer/app/app.go @@ -94,6 +94,9 @@ func action(ctx *cli.Context) error { if cfg.L2Config.BatchProposerConfig.MaxChunksPerBatch <= 0 { log.Crit("cfg.L2Config.BatchProposerConfig.MaxChunksPerBatch must be greater than 0") } + if cfg.L2Config.ChunkProposerConfig.MaxL2GasPerChunk <= 0 { + log.Crit("cfg.L2Config.ChunkProposerConfig.MaxL2GasPerChunk must be greater than 0") + } l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, db, cfg.L2Config.RelayerConfig, genesis.Config, initGenesis, relayer.ServiceTypeL2RollupRelayer, registry) if err != nil { diff --git a/rollup/conf/config.json b/rollup/conf/config.json index 0d88f73d0b..941be1b006 100644 --- a/rollup/conf/config.json +++ b/rollup/conf/config.json @@ -94,6 +94,7 @@ "propose_interval_milliseconds": 100, "max_block_num_per_chunk": 100, "max_tx_num_per_chunk": 100, + "max_l2_gas_per_chunk": 20000000, "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 b6753a8083..cb07e162b1 100644 --- a/rollup/internal/config/l2.go +++ b/rollup/internal/config/l2.go @@ -31,6 +31,7 @@ type ChunkProposerConfig struct { ProposeIntervalMilliseconds uint64 `json:"propose_interval_milliseconds"` MaxBlockNumPerChunk uint64 `json:"max_block_num_per_chunk"` MaxTxNumPerChunk uint64 `json:"max_tx_num_per_chunk"` + MaxL2GasPerChunk uint64 `json:"max_l2_gas_per_chunk"` MaxL1CommitGasPerChunk uint64 `json:"max_l1_commit_gas_per_chunk"` MaxL1CommitCalldataSizePerChunk uint64 `json:"max_l1_commit_calldata_size_per_chunk"` ChunkTimeoutSec uint64 `json:"chunk_timeout_sec"` diff --git a/rollup/internal/controller/watcher/batch_proposer_test.go b/rollup/internal/controller/watcher/batch_proposer_test.go index f1e596912a..9bd03fde4a 100644 --- a/rollup/internal/controller/watcher/batch_proposer_test.go +++ b/rollup/internal/controller/watcher/batch_proposer_test.go @@ -111,6 +111,7 @@ func testBatchProposerLimitsCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: 1, MaxTxNumPerChunk: 10000, + MaxL2GasPerChunk: 20000000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000, MaxRowConsumptionPerChunk: 1000000, @@ -206,6 +207,7 @@ func testBatchCommitGasAndCalldataSizeEstimationCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: 1, MaxTxNumPerChunk: 10000, + MaxL2GasPerChunk: 20_000_000, MaxL1CommitGasPerChunk: 50000000000, MaxL1CommitCalldataSizePerChunk: 1000000, MaxRowConsumptionPerChunk: 1000000, @@ -292,6 +294,7 @@ func testBatchProposerBlobSizeLimitCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: math.MaxUint64, MaxTxNumPerChunk: math.MaxUint64, + MaxL2GasPerChunk: math.MaxUint64, MaxL1CommitGasPerChunk: math.MaxUint64, MaxL1CommitCalldataSizePerChunk: math.MaxUint64, MaxRowConsumptionPerChunk: math.MaxUint64, @@ -387,6 +390,7 @@ func testBatchProposerMaxChunkNumPerBatchLimitCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: math.MaxUint64, MaxTxNumPerChunk: math.MaxUint64, + MaxL2GasPerChunk: math.MaxUint64, MaxL1CommitGasPerChunk: math.MaxUint64, MaxL1CommitCalldataSizePerChunk: math.MaxUint64, MaxRowConsumptionPerChunk: math.MaxUint64, diff --git a/rollup/internal/controller/watcher/bundle_proposer_test.go b/rollup/internal/controller/watcher/bundle_proposer_test.go index a7f69ca810..50f39fdb38 100644 --- a/rollup/internal/controller/watcher/bundle_proposer_test.go +++ b/rollup/internal/controller/watcher/bundle_proposer_test.go @@ -96,6 +96,7 @@ func testBundleProposerLimitsCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: 1, MaxTxNumPerChunk: math.MaxUint64, + MaxL2GasPerChunk: math.MaxUint64, MaxL1CommitGasPerChunk: math.MaxUint64, MaxL1CommitCalldataSizePerChunk: math.MaxUint64, MaxRowConsumptionPerChunk: math.MaxUint64, diff --git a/rollup/internal/controller/watcher/chunk_proposer.go b/rollup/internal/controller/watcher/chunk_proposer.go index ecbcde3127..f20a1ff3c3 100644 --- a/rollup/internal/controller/watcher/chunk_proposer.go +++ b/rollup/internal/controller/watcher/chunk_proposer.go @@ -28,6 +28,7 @@ type ChunkProposer struct { maxBlockNumPerChunk uint64 maxTxNumPerChunk uint64 + maxL2GasPerChunk uint64 maxL1CommitGasPerChunk uint64 maxL1CommitCalldataSizePerChunk uint64 maxRowConsumptionPerChunk uint64 @@ -43,6 +44,7 @@ type ChunkProposer struct { proposeChunkUpdateInfoTotal prometheus.Counter proposeChunkUpdateInfoFailureTotal prometheus.Counter chunkTxNum prometheus.Gauge + chunkL2Gas prometheus.Gauge chunkEstimateL1CommitGas prometheus.Gauge totalL1CommitCalldataSize prometheus.Gauge totalL1CommitBlobSize prometheus.Gauge @@ -66,6 +68,7 @@ func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, minC log.Info("new chunk proposer", "maxBlockNumPerChunk", cfg.MaxBlockNumPerChunk, "maxTxNumPerChunk", cfg.MaxTxNumPerChunk, + "maxL2GasPerChunk", cfg.MaxL2GasPerChunk, "maxL1CommitGasPerChunk", cfg.MaxL1CommitGasPerChunk, "maxL1CommitCalldataSizePerChunk", cfg.MaxL1CommitCalldataSizePerChunk, "maxRowConsumptionPerChunk", cfg.MaxRowConsumptionPerChunk, @@ -81,6 +84,7 @@ func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, minC l2BlockOrm: orm.NewL2Block(db), maxBlockNumPerChunk: cfg.MaxBlockNumPerChunk, maxTxNumPerChunk: cfg.MaxTxNumPerChunk, + maxL2GasPerChunk: cfg.MaxL2GasPerChunk, maxL1CommitGasPerChunk: cfg.MaxL1CommitGasPerChunk, maxL1CommitCalldataSizePerChunk: cfg.MaxL1CommitCalldataSizePerChunk, maxRowConsumptionPerChunk: cfg.MaxRowConsumptionPerChunk, @@ -114,6 +118,10 @@ func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, minC Name: "rollup_propose_chunk_tx_num", Help: "The chunk tx num", }), + chunkL2Gas: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ + Name: "rollup_propose_chunk_l2_gas", + Help: "The chunk l2 gas", + }), chunkEstimateL1CommitGas: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ Name: "rollup_propose_chunk_estimate_l1_commit_gas", Help: "The chunk estimate l1 commit gas", @@ -342,6 +350,7 @@ func (p *ChunkProposer) proposeChunk() error { overEstimatedL1CommitGas := uint64(p.gasCostIncreaseMultiplier * float64(metrics.L1CommitGas)) if metrics.TxNum > p.maxTxNumPerChunk || + metrics.L2Gas > p.maxL2GasPerChunk || metrics.L1CommitCalldataSize > p.maxL1CommitCalldataSizePerChunk || overEstimatedL1CommitGas > p.maxL1CommitGasPerChunk || metrics.CrcMax > p.maxRowConsumptionPerChunk || @@ -356,6 +365,8 @@ func (p *ChunkProposer) proposeChunk() error { log.Debug("breaking limit condition in chunking", "txNum", metrics.TxNum, "maxTxNum", p.maxTxNumPerChunk, + "l2Gas", metrics.L2Gas, + "maxL2Gas", p.maxL2GasPerChunk, "l1CommitCalldataSize", metrics.L1CommitCalldataSize, "maxL1CommitCalldataSize", p.maxL1CommitCalldataSizePerChunk, "l1CommitGas", metrics.L1CommitGas, @@ -409,6 +420,7 @@ func (p *ChunkProposer) recordAllChunkMetrics(metrics *utils.ChunkMetrics) { p.chunkTxNum.Set(float64(metrics.TxNum)) p.maxTxConsumption.Set(float64(metrics.CrcMax)) p.chunkBlocksNum.Set(float64(metrics.NumBlocks)) + p.chunkL2Gas.Set(float64(metrics.L2Gas)) p.totalL1CommitCalldataSize.Set(float64(metrics.L1CommitCalldataSize)) p.chunkEstimateL1CommitGas.Set(float64(metrics.L1CommitGas)) p.totalL1CommitBlobSize.Set(float64(metrics.L1CommitBlobSize)) diff --git a/rollup/internal/controller/watcher/chunk_proposer_test.go b/rollup/internal/controller/watcher/chunk_proposer_test.go index 4886fbebe0..974db79b06 100644 --- a/rollup/internal/controller/watcher/chunk_proposer_test.go +++ b/rollup/internal/controller/watcher/chunk_proposer_test.go @@ -21,6 +21,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name string maxBlockNum uint64 maxTxNum uint64 + maxL2Gas uint64 maxL1CommitGas uint64 maxL1CommitCalldataSize uint64 maxRowConsumption uint64 @@ -32,6 +33,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "NoLimitReached", maxBlockNum: 100, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -42,6 +44,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "Timeout", maxBlockNum: 100, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -53,6 +56,18 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxTxNumPerChunkIs0", maxBlockNum: 10, maxTxNum: 0, + maxL2Gas: 20_000_000, + maxL1CommitGas: 50000000000, + maxL1CommitCalldataSize: 1000000, + maxRowConsumption: 1000000, + chunkTimeoutSec: 1000000000000, + expectedChunksLen: 0, + }, + { + name: "MaxL2GasPerChunkIs0", + maxBlockNum: 10, + maxTxNum: 10, + maxL2Gas: 0, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -63,6 +78,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxL1CommitGasPerChunkIs0", maxBlockNum: 10, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 0, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -73,6 +89,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxL1CommitCalldataSizePerChunkIs0", maxBlockNum: 10, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 0, maxRowConsumption: 1000000, @@ -83,6 +100,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxRowConsumptionPerChunkIs0", maxBlockNum: 100, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 0, @@ -93,6 +111,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxBlockNumPerChunkIs1", maxBlockNum: 1, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -104,6 +123,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxTxNumPerChunkIsFirstBlock", maxBlockNum: 10, maxTxNum: 2, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -111,10 +131,25 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { expectedChunksLen: 1, expectedBlocksInFirstChunk: 1, }, + { + // In this test the second block is not included in the chunk because together + // with the first block it exceeds the maxL2GasPerChunk limit. + name: "MaxL2GasPerChunkIsSecondBlock", + maxBlockNum: 10, + maxTxNum: 10000, + maxL2Gas: 1_153_000, + maxL1CommitGas: 50000000000, + maxL1CommitCalldataSize: 1000000, + maxRowConsumption: 1, + chunkTimeoutSec: 1000000000000, + expectedChunksLen: 1, + expectedBlocksInFirstChunk: 1, + }, { name: "MaxL1CommitGasPerChunkIsFirstBlock", maxBlockNum: 10, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 62500, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1000000, @@ -126,6 +161,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxL1CommitCalldataSizePerChunkIsFirstBlock", maxBlockNum: 10, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 60, maxRowConsumption: 1000000, @@ -137,6 +173,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { name: "MaxRowConsumptionPerChunkIs1", maxBlockNum: 10, maxTxNum: 10000, + maxL2Gas: 20_000_000, maxL1CommitGas: 50000000000, maxL1CommitCalldataSize: 1000000, maxRowConsumption: 1, @@ -158,6 +195,7 @@ func testChunkProposerLimitsCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: tt.maxBlockNum, MaxTxNumPerChunk: tt.maxTxNum, + MaxL2GasPerChunk: tt.maxL2Gas, MaxL1CommitGasPerChunk: tt.maxL1CommitGas, MaxL1CommitCalldataSizePerChunk: tt.maxL1CommitCalldataSize, MaxRowConsumptionPerChunk: tt.maxRowConsumption, @@ -208,6 +246,7 @@ func testChunkProposerBlobSizeLimitCodecV4(t *testing.T) { cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: 255, MaxTxNumPerChunk: math.MaxUint64, + MaxL2GasPerChunk: math.MaxUint64, MaxL1CommitGasPerChunk: math.MaxUint64, MaxL1CommitCalldataSizePerChunk: math.MaxUint64, MaxRowConsumptionPerChunk: math.MaxUint64, diff --git a/rollup/internal/utils/utils.go b/rollup/internal/utils/utils.go index e23860f81a..4f9a1f91d1 100644 --- a/rollup/internal/utils/utils.go +++ b/rollup/internal/utils/utils.go @@ -12,6 +12,7 @@ import ( type ChunkMetrics struct { NumBlocks uint64 TxNum uint64 + L2Gas uint64 CrcMax uint64 FirstBlockTimestamp uint64 @@ -35,6 +36,11 @@ func CalculateChunkMetrics(chunk *encoding.Chunk, codecVersion encoding.CodecVer FirstBlockTimestamp: chunk.Blocks[0].Header.Time, } + // Get total L2 gas for chunk + for _, block := range chunk.Blocks { + metrics.L2Gas += block.Header.GasUsed + } + var err error metrics.CrcMax, err = chunk.CrcMax() if err != nil {