Skip to content

Commit

Permalink
feat: make chunk proposer respect forks
Browse files Browse the repository at this point in the history
  • Loading branch information
omerfirmak committed Mar 4, 2024
1 parent 650ffe1 commit 8f146de
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 9 deletions.
9 changes: 9 additions & 0 deletions common/utils/flags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package utils

import (
"scroll-tech/common/network"

"github.com/urfave/cli/v2"
)

Expand All @@ -16,6 +18,7 @@ var (
&MetricsAddr,
&MetricsPort,
&ServicePortFlag,
&NetworkFlag,
}
// RollupRelayerFlags contains flags only used in rollup-relayer
RollupRelayerFlags = []cli.Flag{
Expand Down Expand Up @@ -83,4 +86,10 @@ var (
Usage: "Port that the service will listen on",
Value: 8080,
}
// Network that we will operate on
NetworkFlag = cli.StringFlag{
Name: "network",
Usage: "Network that we will operate on",
Value: string(network.Mainnet),
}
)
8 changes: 7 additions & 1 deletion rollup/cmd/rollup_relayer/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/urfave/cli/v2"

"scroll-tech/common/database"
"scroll-tech/common/network"
"scroll-tech/common/observability"
"scroll-tech/common/utils"
"scroll-tech/common/version"
Expand Down Expand Up @@ -78,7 +79,12 @@ func action(ctx *cli.Context) error {
log.Crit("failed to create l2 relayer", "config file", cfgFile, "error", err)
}

chunkProposer := watcher.NewChunkProposer(subCtx, cfg.L2Config.ChunkProposerConfig, db, registry)
network := network.Network(ctx.String(utils.NetworkFlag.Name))
if !network.IsKnown() {
log.Crit("failed to detect network", "config file", cfgFile, "network", network)
}

chunkProposer := watcher.NewChunkProposer(subCtx, cfg.L2Config.ChunkProposerConfig, network.GenesisConfig(), db, registry)
if err != nil {
log.Crit("failed to create chunkProposer", "config file", cfgFile, "error", err)
}
Expand Down
5 changes: 3 additions & 2 deletions rollup/internal/controller/watcher/batch_proposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"testing"

"github.com/scroll-tech/go-ethereum/params"
"github.com/stretchr/testify/assert"

"scroll-tech/common/database"
Expand Down Expand Up @@ -102,7 +103,7 @@ func testBatchProposerLimits(t *testing.T) {
MaxRowConsumptionPerChunk: 1000000,
ChunkTimeoutSec: 300,
GasCostIncreaseMultiplier: 1.2,
}, db, nil)
}, &params.ChainConfig{}, db, nil)
cp.TryProposeChunk() // chunk1 contains block1
cp.TryProposeChunk() // chunk2 contains block2

Expand Down Expand Up @@ -161,7 +162,7 @@ func testBatchCommitGasAndCalldataSizeEstimation(t *testing.T) {
MaxRowConsumptionPerChunk: 1000000,
ChunkTimeoutSec: 300,
GasCostIncreaseMultiplier: 1.2,
}, db, nil)
}, &params.ChainConfig{}, db, nil)
cp.TryProposeChunk() // chunk1 contains block1
cp.TryProposeChunk() // chunk2 contains block2

Expand Down
33 changes: 28 additions & 5 deletions rollup/internal/controller/watcher/chunk_proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"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"
Expand Down Expand Up @@ -58,6 +60,7 @@ type ChunkProposer struct {
maxRowConsumptionPerChunk uint64
chunkTimeoutSec uint64
gasCostIncreaseMultiplier float64
forkHeights []uint64

chunkProposerCircleTotal prometheus.Counter
proposeChunkFailureTotal prometheus.Counter
Expand All @@ -74,14 +77,16 @@ type ChunkProposer struct {
}

// NewChunkProposer creates a new ChunkProposer instance.
func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, db *gorm.DB, reg prometheus.Registerer) *ChunkProposer {
func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, chainCfg *params.ChainConfig, db *gorm.DB, reg prometheus.Registerer) *ChunkProposer {
forkHeights := network.CollectSortedForkHeights(chainCfg)
log.Debug("new chunk proposer",
"maxTxNumPerChunk", cfg.MaxTxNumPerChunk,
"maxL1CommitGasPerChunk", cfg.MaxL1CommitGasPerChunk,
"maxL1CommitCalldataSizePerChunk", cfg.MaxL1CommitCalldataSizePerChunk,
"maxRowConsumptionPerChunk", cfg.MaxRowConsumptionPerChunk,
"chunkTimeoutSec", cfg.ChunkTimeoutSec,
"gasCostIncreaseMultiplier", cfg.GasCostIncreaseMultiplier)
"gasCostIncreaseMultiplier", cfg.GasCostIncreaseMultiplier,
"forkHeights", forkHeights)

return &ChunkProposer{
ctx: ctx,
Expand All @@ -95,6 +100,7 @@ func NewChunkProposer(ctx context.Context, cfg *config.ChunkProposerConfig, db *
maxRowConsumptionPerChunk: cfg.MaxRowConsumptionPerChunk,
chunkTimeoutSec: cfg.ChunkTimeoutSec,
gasCostIncreaseMultiplier: cfg.GasCostIncreaseMultiplier,
forkHeights: forkHeights,

chunkProposerCircleTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{
Name: "rollup_propose_chunk_circle_total",
Expand Down Expand Up @@ -184,14 +190,31 @@ func (p *ChunkProposer) updateChunkInfoInDB(chunk *types.Chunk) error {
return err
}

// blocksUntilFork returns the number of blocks until the next fork
// returns 0 if there is no fork scheduled for the future
func blocksUntilFork(blockHeight uint64, forkHeights []uint64) uint64 {
for _, forkHeight := range forkHeights {
if forkHeight > blockHeight {
return forkHeight - blockHeight
}
}
return 0
}

func (p *ChunkProposer) proposeChunk() (*types.Chunk, error) {
unchunkedBlockHeight, err := p.chunkOrm.GetUnchunkedBlockHeight(p.ctx)
if err != nil {
return nil, err
}

// select at most p.maxBlockNumPerChunk blocks
blocks, err := p.l2BlockOrm.GetL2WrappedBlocksGEHeight(p.ctx, unchunkedBlockHeight, int(p.maxBlockNumPerChunk))
maxBlocksThisChunk := p.maxBlockNumPerChunk
blocksUntilFork := blocksUntilFork(unchunkedBlockHeight, p.forkHeights)
if blocksUntilFork != 0 && blocksUntilFork < maxBlocksThisChunk {
maxBlocksThisChunk = blocksUntilFork
}

// select at most maxBlocksThisChunk blocks
blocks, err := p.l2BlockOrm.GetL2WrappedBlocksGEHeight(p.ctx, unchunkedBlockHeight, int(maxBlocksThisChunk))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -294,7 +317,7 @@ func (p *ChunkProposer) proposeChunk() (*types.Chunk, error) {

currentTimeSec := uint64(time.Now().Unix())
if chunk.Blocks[0].Header.Time+p.chunkTimeoutSec < currentTimeSec ||
uint64(len(chunk.Blocks)) == p.maxBlockNumPerChunk {
uint64(len(chunk.Blocks)) == maxBlocksThisChunk {
if chunk.Blocks[0].Header.Time+p.chunkTimeoutSec < currentTimeSec {
log.Warn("first block timeout",
"block number", chunk.Blocks[0].Header.Number,
Expand Down
58 changes: 58 additions & 0 deletions rollup/internal/controller/watcher/chunk_proposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package watcher

import (
"context"
"math/big"
"testing"

"github.com/scroll-tech/go-ethereum/params"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"scroll-tech/common/database"
"scroll-tech/common/types"
Expand All @@ -22,6 +25,7 @@ func testChunkProposerLimits(t *testing.T) {
maxL1CommitCalldataSize uint64
maxRowConsumption uint64
chunkTimeoutSec uint64
forkBlock *big.Int
expectedChunksLen int
expectedBlocksInFirstChunk int // only be checked when expectedChunksLen > 0
}{
Expand Down Expand Up @@ -141,6 +145,18 @@ func testChunkProposerLimits(t *testing.T) {
expectedChunksLen: 1,
expectedBlocksInFirstChunk: 1,
},
{
name: "ForkBlockReached",
maxBlockNum: 100,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
expectedBlocksInFirstChunk: 1,
forkBlock: big.NewInt(2),
},
}

for _, tt := range tests {
Expand All @@ -160,6 +176,8 @@ func testChunkProposerLimits(t *testing.T) {
MaxRowConsumptionPerChunk: tt.maxRowConsumption,
ChunkTimeoutSec: tt.chunkTimeoutSec,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{
HomesteadBlock: tt.forkBlock,
}, db, nil)
cp.TryProposeChunk()

Expand All @@ -180,3 +198,43 @@ func testChunkProposerLimits(t *testing.T) {
})
}
}

func TestBlocksUntilFork(t *testing.T) {
tests := map[string]struct {
block uint64
forks []uint64
expected uint64
}{
"NoFork": {
block: 44,
forks: []uint64{},
expected: 0,
},
"BeforeFork": {
block: 0,
forks: []uint64{1, 5},
expected: 1,
},
"OnFork": {
block: 1,
forks: []uint64{1, 5},
expected: 4,
},
"OnLastFork": {
block: 5,
forks: []uint64{1, 5},
expected: 0,
},
"AfterFork": {
block: 5,
forks: []uint64{1, 5},
expected: 0,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
require.Equal(t, test.expected, blocksUntilFork(test.block, test.forks))
})
}
}
3 changes: 2 additions & 1 deletion rollup/tests/rollup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/scroll-tech/go-ethereum/common"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/params"
"github.com/stretchr/testify/assert"

"scroll-tech/common/database"
Expand Down Expand Up @@ -91,7 +92,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
MaxL1CommitCalldataSizePerChunk: 1000000,
MaxRowConsumptionPerChunk: 1048319,
ChunkTimeoutSec: 300,
}, db, nil)
}, &params.ChainConfig{}, db, nil)
cp.TryProposeChunk()

batchOrm := orm.NewBatch(db)
Expand Down

0 comments on commit 8f146de

Please sign in to comment.