Skip to content

Commit 78cf923

Browse files
author
colinlyguo
committed
support start from a specific l2 block
1 parent 9fc3ad5 commit 78cf923

File tree

5 files changed

+97
-16
lines changed

5 files changed

+97
-16
lines changed

common/utils/flags.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ var (
2222
RollupRelayerFlags = []cli.Flag{
2323
&MinCodecVersionFlag,
2424
}
25+
// ProposerToolFlags contains flags only used in proposer tool
26+
ProposerToolFlags = []cli.Flag{
27+
&StartL2BlockFlag,
28+
}
2529
// ConfigFileFlag load json type config file.
2630
ConfigFileFlag = cli.StringFlag{
2731
Name: "config",
@@ -90,4 +94,10 @@ var (
9094
Usage: "Minimum required codec version for the chunk/batch/bundle proposers",
9195
Required: true,
9296
}
97+
// StartL2BlockFlag indicates the start L2 block number for proposer tool
98+
StartL2BlockFlag = cli.Uint64Flag{
99+
Name: "start-l2-block",
100+
Usage: "Start L2 block number for proposer tool",
101+
Value: 0,
102+
}
93103
)

rollup/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ You can:
5050

5151
1. Set genesis config to enable desired hardforks in [`proposer-tool-genesis.json`](./proposer-tool-genesis.json).
5252
2. Set proposer config in [`proposer-tool-config.json`](./proposer-tool-config.json) for data analysis.
53+
3. Set `start-l2-block` in the launch command of proposer-tool in [`docker-compose-proposer-tool.yml`](./docker-compose-proposer-tool.yml) to the block number you want to start from. The default is `0`, which means starting from the genesis block.
5354

5455
### Start the proposer tool using docker-compose
5556

57+
Prerequisite: an RPC URL to an archive L2 node. The default url in [`proposer-tool-config.json`](./proposer-tool-config.json) is `https://rpc.scroll.io`.
58+
5659
```
5760
cd rollup
5861
DOCKER_BUILDKIT=1 docker-compose -f docker-compose-proposer-tool.yml up -d

rollup/cmd/proposer_tool/app/app.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/urfave/cli/v2"
1818

1919
"scroll-tech/common/database"
20-
"scroll-tech/common/types"
2120
"scroll-tech/common/utils"
2221
"scroll-tech/common/version"
2322
"scroll-tech/database/migrate"
@@ -39,6 +38,7 @@ func init() {
3938
app.Version = version.Version
4039
app.Flags = append(app.Flags, utils.CommonFlags...)
4140
app.Flags = append(app.Flags, utils.RollupRelayerFlags...)
41+
app.Flags = append(app.Flags, utils.ProposerToolFlags...)
4242
app.Commands = []*cli.Command{}
4343
app.Before = func(ctx *cli.Context) error {
4444
return utils.LogSetup(ctx)
@@ -92,28 +92,33 @@ func action(ctx *cli.Context) error {
9292
log.Crit("failed to connect l2 geth", "config file", cfgFile, "error", err)
9393
}
9494

95-
genesisHeader, err := l2Client.HeaderByNumber(subCtx, big.NewInt(0))
95+
startL2BlockHeight := ctx.Uint64(utils.StartL2BlockFlag.Name)
96+
startL2Block, err := l2Client.BlockByNumber(context.Background(), big.NewInt(int64(startL2BlockHeight)))
9697
if err != nil {
97-
return fmt.Errorf("failed to retrieve L2 genesis header: %v", err)
98+
log.Crit("failed to get start l2 block", "startL2BlockHeight", startL2BlockHeight, "error", err)
9899
}
99100

100-
chunk := &encoding.Chunk{
101-
Blocks: []*encoding.Block{{
102-
Header: genesisHeader,
103-
Transactions: nil,
104-
WithdrawRoot: common.Hash{},
105-
RowConsumption: &gethTypes.RowConsumption{},
106-
}},
107-
}
101+
chunk := &encoding.Chunk{Blocks: []*encoding.Block{{Header: startL2Block.Header()}}}
108102

109-
var dbChunk *orm.Chunk
110-
dbChunk, err = orm.NewChunk(db).InsertChunk(subCtx, chunk, encoding.CodecV0, rutils.ChunkMetrics{})
103+
prevChunk, err := orm.NewChunk(dbForReplay).GetParentChunkByBlockNumber(subCtx, startL2BlockHeight)
111104
if err != nil {
112-
log.Crit("failed to insert chunk", "error", err)
105+
log.Crit("failed to get previous chunk", "error", err)
113106
}
114107

115-
if err = orm.NewChunk(db).UpdateProvingStatus(subCtx, dbChunk.Hash, types.ProvingTaskVerified); err != nil {
116-
log.Crit("failed to update genesis chunk proving status", "error", err)
108+
var startQueueIndex uint64
109+
if prevChunk != nil {
110+
startQueueIndex = prevChunk.TotalL1MessagesPoppedBefore + prevChunk.TotalL1MessagesPoppedInChunk
111+
}
112+
113+
for _, tx := range startL2Block.Transactions() {
114+
if tx.Type() == gethTypes.L1MessageTxType {
115+
startQueueIndex++
116+
}
117+
}
118+
119+
_, err = orm.NewChunk(db).InsertTestChunkForProposerTool(subCtx, chunk, encoding.CodecV0, startQueueIndex)
120+
if err != nil {
121+
log.Crit("failed to insert chunk", "error", err)
117122
}
118123

119124
batch := &encoding.Batch{

rollup/docker-compose-proposer-tool.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ services:
2828
"--config", "/app/conf/proposer-tool-config.json",
2929
"--genesis", "/app/conf/proposer-tool-genesis.json",
3030
"--min-codec-version", "4",
31+
"--start-l2-block", "10000",
3132
"--log.debug", "--verbosity", "3"
3233
]
3334
volumes:

rollup/internal/orm/chunk.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@ func (o *Chunk) GetChunksByBatchHash(ctx context.Context, batchHash string) ([]*
179179
return chunks, nil
180180
}
181181

182+
// GetParentChunkByBlockNumber retrieves the parent chunk by block number
183+
// for test
184+
func (o *Chunk) GetParentChunkByBlockNumber(ctx context.Context, blockNumber uint64) (*Chunk, error) {
185+
db := o.db.WithContext(ctx)
186+
db = db.Model(&Chunk{})
187+
db = db.Where("end_block_number < ?", blockNumber)
188+
db = db.Order("end_block_number DESC")
189+
db = db.Limit(1)
190+
191+
var chunk Chunk
192+
if err := db.First(&chunk).Error; err != nil {
193+
if errors.Is(err, gorm.ErrRecordNotFound) {
194+
return nil, nil
195+
}
196+
return nil, fmt.Errorf("Chunk.GetParentChunkByBlockNumber error: %w", err)
197+
}
198+
return &chunk, nil
199+
}
200+
182201
// InsertChunk inserts a new chunk into the database.
183202
func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, codecVersion encoding.CodecVersion, metrics rutils.ChunkMetrics, dbTX ...*gorm.DB) (*Chunk, error) {
184203
if chunk == nil || len(chunk.Blocks) == 0 {
@@ -259,6 +278,49 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, codecVer
259278
return &newChunk, nil
260279
}
261280

281+
// InsertTestChunkForProposerTool inserts a new chunk into the database only for testing purposes in the proposer tool.
282+
func (o *Chunk) InsertTestChunkForProposerTool(ctx context.Context, chunk *encoding.Chunk, codecVersion encoding.CodecVersion, totalL1MessagePoppedBefore uint64, dbTX ...*gorm.DB) (*Chunk, error) {
283+
if chunk == nil || len(chunk.Blocks) == 0 {
284+
return nil, errors.New("invalid args")
285+
}
286+
287+
chunkHash, err := rutils.GetChunkHash(chunk, totalL1MessagePoppedBefore, codecVersion)
288+
if err != nil {
289+
log.Error("failed to get chunk hash", "err", err)
290+
return nil, fmt.Errorf("Chunk.InsertChunk error: %w", err)
291+
}
292+
293+
numBlocks := len(chunk.Blocks)
294+
newChunk := Chunk{
295+
Index: 0,
296+
Hash: chunkHash.Hex(),
297+
StartBlockNumber: chunk.Blocks[0].Header.Number.Uint64(),
298+
StartBlockHash: chunk.Blocks[0].Header.Hash().Hex(),
299+
EndBlockNumber: chunk.Blocks[numBlocks-1].Header.Number.Uint64(),
300+
EndBlockHash: chunk.Blocks[numBlocks-1].Header.Hash().Hex(),
301+
TotalL2TxGas: chunk.TotalGasUsed(),
302+
TotalL2TxNum: chunk.NumL2Transactions(),
303+
StartBlockTime: chunk.Blocks[0].Header.Time,
304+
TotalL1MessagesPoppedBefore: totalL1MessagePoppedBefore,
305+
StateRoot: chunk.Blocks[numBlocks-1].Header.Root.Hex(),
306+
WithdrawRoot: chunk.Blocks[numBlocks-1].WithdrawRoot.Hex(),
307+
CodecVersion: int16(codecVersion),
308+
}
309+
310+
db := o.db
311+
if len(dbTX) > 0 && dbTX[0] != nil {
312+
db = dbTX[0]
313+
}
314+
db = db.WithContext(ctx)
315+
db = db.Model(&Chunk{})
316+
317+
if err := db.Create(&newChunk).Error; err != nil {
318+
return nil, fmt.Errorf("Chunk.InsertChunk error: %w, chunk hash: %v", err, newChunk.Hash)
319+
}
320+
321+
return &newChunk, nil
322+
}
323+
262324
// UpdateProvingStatus updates the proving status of a chunk.
263325
func (o *Chunk) UpdateProvingStatus(ctx context.Context, hash string, status types.ProvingStatus, dbTX ...*gorm.DB) error {
264326
updateFields := make(map[string]interface{})

0 commit comments

Comments
 (0)