From 4c6d7b7debdf8cb8ad518720bda53abb51b5dc78 Mon Sep 17 00:00:00 2001 From: colin <102356659+colinlyguo@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:16:54 +0800 Subject: [PATCH] refactor(batch): removing db fields in batch encoding type (#1196) --- common/types/encoding/codecv0/codecv0_test.go | 37 ----------- common/types/encoding/da.go | 6 -- common/version/version.go | 2 +- coordinator/internal/orm/batch.go | 65 +++++++++++++++++-- coordinator/internal/orm/chunk.go | 17 +++-- .../internal/controller/relayer/l2_relayer.go | 4 -- .../controller/relayer/l2_relayer_test.go | 32 --------- .../controller/watcher/batch_proposer.go | 9 --- rollup/internal/orm/batch.go | 62 ++++++++++++++++-- rollup/internal/orm/chunk.go | 29 +++++---- rollup/internal/orm/orm_test.go | 8 --- rollup/tests/gas_oracle_test.go | 10 --- tests/integration-test/integration_test.go | 12 ---- tests/integration-test/orm/batch.go | 65 +++++++++++++++++-- tests/integration-test/orm/chunk.go | 17 +++-- 15 files changed, 214 insertions(+), 161 deletions(-) diff --git a/common/types/encoding/codecv0/codecv0_test.go b/common/types/encoding/codecv0/codecv0_test.go index 03e6eb23f..e70b177c9 100644 --- a/common/types/encoding/codecv0/codecv0_test.go +++ b/common/types/encoding/codecv0/codecv0_test.go @@ -99,10 +99,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err := EstimateBatchL1CommitCalldataSize(batch) @@ -154,10 +150,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -211,10 +203,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -276,20 +264,11 @@ func TestCodecV0(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 61, len(chunkBytes2)) - daChunk1Hash, err := daChunk1.Hash() - assert.NoError(t, err) - daChunk2Hash, err := daChunk2.Hash() - assert.NoError(t, err) - batch = &encoding.Batch{ Index: 1, TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - EndChunkIndex: 1, - StartChunkHash: daChunk1Hash, - EndChunkHash: daChunk2Hash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -343,10 +322,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 37, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -400,10 +375,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -457,10 +428,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) @@ -514,10 +481,6 @@ func TestCodecV0(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: parentBatchHash, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } batchL1CommitCalldataSize, err = EstimateBatchL1CommitCalldataSize(batch) diff --git a/common/types/encoding/da.go b/common/types/encoding/da.go index efc61226e..4e5a1c1cc 100644 --- a/common/types/encoding/da.go +++ b/common/types/encoding/da.go @@ -27,12 +27,6 @@ type Batch struct { TotalL1MessagePoppedBefore uint64 ParentBatchHash common.Hash Chunks []*Chunk - - // Only used in updating db info. - StartChunkIndex uint64 - EndChunkIndex uint64 - StartChunkHash common.Hash - EndChunkHash common.Hash } // NumL1Messages returns the number of L1 messages in this block. diff --git a/common/version/version.go b/common/version/version.go index e98f39864..1b0524252 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.3.71" +var tag = "v4.3.72" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/coordinator/internal/orm/batch.go b/coordinator/internal/orm/batch.go index e9bcab798..d5d86f86e 100644 --- a/coordinator/internal/orm/batch.go +++ b/coordinator/internal/orm/batch.go @@ -167,6 +167,9 @@ func (o *Batch) GetLatestBatch(ctx context.Context) (*Batch, error) { var latestBatch Batch if err := db.First(&latestBatch).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } return nil, fmt.Errorf("Batch.GetLatestBatch error: %w", err) } return &latestBatch, nil @@ -190,21 +193,73 @@ func (o *Batch) InsertBatch(ctx context.Context, batch *encoding.Batch, dbTX ... return nil, errors.New("invalid args: batch is nil") } + numChunks := uint64(len(batch.Chunks)) + if numChunks == 0 { + return nil, errors.New("invalid args: batch contains 0 chunk") + } + daBatch, err := codecv0.NewDABatch(batch) if err != nil { log.Error("failed to create new DA batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, - "parent hash", batch.ParentBatchHash, "number of chunks", len(batch.Chunks), "err", err) + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) return nil, err } + var startChunkIndex uint64 + parentBatch, err := o.GetLatestBatch(ctx) + if err != nil { + log.Error("failed to get latest batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + // if parentBatch==nil then err==gorm.ErrRecordNotFound, which means there's + // no batch record in the db, we then use default empty values for the creating batch; + // if parentBatch!=nil then err==nil, then we fill the parentBatch-related data into the creating batch + if parentBatch != nil { + startChunkIndex = parentBatch.EndChunkIndex + 1 + } + + startDAChunk, err := codecv0.NewDAChunk(batch.Chunks[0], batch.TotalL1MessagePoppedBefore) + if err != nil { + log.Error("failed to create start DA chunk", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + startDAChunkHash, err := startDAChunk.Hash() + if err != nil { + log.Error("failed to get start DA chunk hash", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + totalL1MessagePoppedBeforeEndDAChunk := batch.TotalL1MessagePoppedBefore + for i := uint64(0); i < numChunks-1; i++ { + totalL1MessagePoppedBeforeEndDAChunk += batch.Chunks[i].NumL1Messages(totalL1MessagePoppedBeforeEndDAChunk) + } + endDAChunk, err := codecv0.NewDAChunk(batch.Chunks[numChunks-1], totalL1MessagePoppedBeforeEndDAChunk) + if err != nil { + log.Error("failed to create end DA chunk", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + endDAChunkHash, err := endDAChunk.Hash() + if err != nil { + log.Error("failed to get end DA chunk hash", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + newBatch := Batch{ Index: batch.Index, Hash: daBatch.Hash().Hex(), - StartChunkHash: batch.StartChunkHash.Hex(), - StartChunkIndex: batch.StartChunkIndex, - EndChunkHash: batch.EndChunkHash.Hex(), - EndChunkIndex: batch.EndChunkIndex, + StartChunkHash: startDAChunkHash.Hex(), + StartChunkIndex: startChunkIndex, + EndChunkHash: endDAChunkHash.Hex(), + EndChunkIndex: startChunkIndex + numChunks - 1, StateRoot: batch.StateRoot().Hex(), WithdrawRoot: batch.WithdrawRoot().Hex(), ParentBatchHash: batch.ParentBatchHash.Hex(), diff --git a/coordinator/internal/orm/chunk.go b/coordinator/internal/orm/chunk.go index 141f49a29..bf253ea96 100644 --- a/coordinator/internal/orm/chunk.go +++ b/coordinator/internal/orm/chunk.go @@ -153,15 +153,18 @@ func (o *Chunk) GetProofsByBatchHash(ctx context.Context, batchHash string) ([]* return proofs, nil } -// GetLatestChunk retrieves the latest chunk from the database. -func (o *Chunk) GetLatestChunk(ctx context.Context) (*Chunk, error) { +// getLatestChunk retrieves the latest chunk from the database. +func (o *Chunk) getLatestChunk(ctx context.Context) (*Chunk, error) { db := o.db.WithContext(ctx) db = db.Model(&Chunk{}) db = db.Order("index desc") var latestChunk Chunk if err := db.First(&latestChunk).Error; err != nil { - return nil, fmt.Errorf("Chunk.GetLatestChunk error: %w", err) + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, fmt.Errorf("Chunk.getLatestChunk error: %w", err) } return &latestChunk, nil } @@ -230,15 +233,15 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, dbTX ... var totalL1MessagePoppedBefore uint64 var parentChunkHash string var parentChunkStateRoot string - parentChunk, err := o.GetLatestChunk(ctx) - if err != nil && !errors.Is(errors.Unwrap(err), gorm.ErrRecordNotFound) { + parentChunk, err := o.getLatestChunk(ctx) + if err != nil { log.Error("failed to get latest chunk", "err", err) return nil, fmt.Errorf("Chunk.InsertChunk error: %w", err) } // if parentChunk==nil then err==gorm.ErrRecordNotFound, which means there's - // not chunk record in the db, we then use default empty values for the creating chunk; - // if parentChunk!=nil then err=nil, then we fill the parentChunk-related data into the creating chunk + // no chunk record in the db, we then use default empty values for the creating chunk; + // if parentChunk!=nil then err==nil, then we fill the parentChunk-related data into the creating chunk if parentChunk != nil { chunkIndex = parentChunk.Index + 1 totalL1MessagePoppedBefore = parentChunk.TotalL1MessagesPoppedBefore + parentChunk.TotalL1MessagesPoppedInChunk diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go index a41b6e347..96500f017 100644 --- a/rollup/internal/controller/relayer/l2_relayer.go +++ b/rollup/internal/controller/relayer/l2_relayer.go @@ -203,10 +203,6 @@ func (r *Layer2Relayer) initializeGenesis() error { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: common.HexToHash(dbChunk.Hash), - EndChunkHash: common.HexToHash(dbChunk.Hash), } var dbBatch *orm.Batch diff --git a/rollup/internal/controller/relayer/l2_relayer_test.go b/rollup/internal/controller/relayer/l2_relayer_test.go index 4e58c3bc3..2d055d0a5 100644 --- a/rollup/internal/controller/relayer/l2_relayer_test.go +++ b/rollup/internal/controller/relayer/l2_relayer_test.go @@ -66,10 +66,6 @@ func testL2RelayerProcessPendingBatches(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } batchOrm := orm.NewBatch(db) @@ -97,10 +93,6 @@ func testL2RelayerProcessCommittedBatches(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } batchOrm := orm.NewBatch(db) @@ -149,10 +141,6 @@ func testL2RelayerFinalizeTimeoutBatches(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } batchOrm := orm.NewBatch(db) @@ -192,10 +180,6 @@ func testL2RelayerCommitConfirm(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } dbBatch, err := batchOrm.InsertBatch(context.Background(), batch) @@ -251,10 +235,6 @@ func testL2RelayerFinalizeConfirm(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } dbBatch, err := batchOrm.InsertBatch(context.Background(), batch) @@ -298,10 +278,6 @@ func testL2RelayerGasOracleConfirm(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 0, - EndChunkHash: chunkHash1, } batchOrm := orm.NewBatch(db) @@ -313,10 +289,6 @@ func testL2RelayerGasOracleConfirm(t *testing.T) { TotalL1MessagePoppedBefore: batch1.TotalL1MessagePoppedBefore, ParentBatchHash: common.HexToHash(dbBatch1.Hash), Chunks: []*encoding.Chunk{chunk2}, - StartChunkIndex: 1, - StartChunkHash: chunkHash2, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } dbBatch2, err := batchOrm.InsertBatch(context.Background(), batch2) @@ -473,10 +445,6 @@ func testGetBatchStatusByIndex(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1, chunk2}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } batchOrm := orm.NewBatch(db) diff --git a/rollup/internal/controller/watcher/batch_proposer.go b/rollup/internal/controller/watcher/batch_proposer.go index 1c12cce01..da29959fd 100644 --- a/rollup/internal/controller/watcher/batch_proposer.go +++ b/rollup/internal/controller/watcher/batch_proposer.go @@ -234,10 +234,6 @@ func (p *BatchProposer) proposeBatch() (*encoding.Batch, error) { "maxL1CommitGasPerBatch", p.maxL1CommitGasPerBatch) batch.Chunks = batch.Chunks[:len(batch.Chunks)-1] - batch.StartChunkIndex = dbChunks[0].Index - batch.EndChunkIndex = dbChunks[batch.NumChunks()-1].Index - batch.StartChunkHash = common.HexToHash(dbChunks[0].Hash) - batch.EndChunkHash = common.HexToHash(dbChunks[batch.NumChunks()-1].Hash) totalL1CommitCalldataSize, err := codecv0.EstimateBatchL1CommitCalldataSize(&batch) if err != nil { @@ -286,11 +282,6 @@ func (p *BatchProposer) proposeBatch() (*encoding.Batch, error) { p.totalL1CommitGas.Set(float64(totalL1CommitGas)) p.batchChunksNum.Set(float64(batch.NumChunks())) - batch.StartChunkIndex = dbChunks[0].Index - batch.EndChunkIndex = dbChunks[batch.NumChunks()-1].Index - batch.StartChunkHash = common.HexToHash(dbChunks[0].Hash) - batch.EndChunkHash = common.HexToHash(dbChunks[batch.NumChunks()-1].Hash) - return &batch, nil } diff --git a/rollup/internal/orm/batch.go b/rollup/internal/orm/batch.go index bfc5bb197..eb675f63f 100644 --- a/rollup/internal/orm/batch.go +++ b/rollup/internal/orm/batch.go @@ -231,11 +231,16 @@ func (o *Batch) InsertBatch(ctx context.Context, batch *encoding.Batch, dbTX ... return nil, errors.New("invalid args: batch is nil") } + numChunks := uint64(len(batch.Chunks)) + if numChunks == 0 { + return nil, errors.New("invalid args: batch contains 0 chunk") + } + daBatch, err := codecv0.NewDABatch(batch) if err != nil { log.Error("failed to create new DA batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, - "parent hash", batch.ParentBatchHash, "number of chunks", len(batch.Chunks), "err", err) + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) return nil, err } @@ -255,13 +260,60 @@ func (o *Batch) InsertBatch(ctx context.Context, batch *encoding.Batch, dbTX ... return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) } + var startChunkIndex uint64 + parentBatch, err := o.GetLatestBatch(ctx) + if err != nil { + log.Error("failed to get latest batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + // if parentBatch==nil then err==gorm.ErrRecordNotFound, which means there's + // no batch record in the db, we then use default empty values for the creating batch; + // if parentBatch!=nil then err==nil, then we fill the parentBatch-related data into the creating batch + if parentBatch != nil { + startChunkIndex = parentBatch.EndChunkIndex + 1 + } + + startDAChunk, err := codecv0.NewDAChunk(batch.Chunks[0], batch.TotalL1MessagePoppedBefore) + if err != nil { + log.Error("failed to create start DA chunk", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + startDAChunkHash, err := startDAChunk.Hash() + if err != nil { + log.Error("failed to get start DA chunk hash", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + totalL1MessagePoppedBeforeEndDAChunk := batch.TotalL1MessagePoppedBefore + for i := uint64(0); i < numChunks-1; i++ { + totalL1MessagePoppedBeforeEndDAChunk += batch.Chunks[i].NumL1Messages(totalL1MessagePoppedBeforeEndDAChunk) + } + endDAChunk, err := codecv0.NewDAChunk(batch.Chunks[numChunks-1], totalL1MessagePoppedBeforeEndDAChunk) + if err != nil { + log.Error("failed to create end DA chunk", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + endDAChunkHash, err := endDAChunk.Hash() + if err != nil { + log.Error("failed to get end DA chunk hash", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + newBatch := Batch{ Index: batch.Index, Hash: daBatch.Hash().Hex(), - StartChunkHash: batch.StartChunkHash.Hex(), - StartChunkIndex: batch.StartChunkIndex, - EndChunkHash: batch.EndChunkHash.Hex(), - EndChunkIndex: batch.EndChunkIndex, + StartChunkHash: startDAChunkHash.Hex(), + StartChunkIndex: startChunkIndex, + EndChunkHash: endDAChunkHash.Hex(), + EndChunkIndex: startChunkIndex + numChunks - 1, StateRoot: batch.StateRoot().Hex(), WithdrawRoot: batch.WithdrawRoot().Hex(), ParentBatchHash: batch.ParentBatchHash.Hex(), diff --git a/rollup/internal/orm/chunk.go b/rollup/internal/orm/chunk.go index b38f2b136..a3c048d61 100644 --- a/rollup/internal/orm/chunk.go +++ b/rollup/internal/orm/chunk.go @@ -89,15 +89,18 @@ func (o *Chunk) GetChunksInRange(ctx context.Context, startIndex uint64, endInde return chunks, nil } -// GetLatestChunk retrieves the latest chunk from the database. -func (o *Chunk) GetLatestChunk(ctx context.Context) (*Chunk, error) { +// getLatestChunk retrieves the latest chunk from the database. +func (o *Chunk) getLatestChunk(ctx context.Context) (*Chunk, error) { db := o.db.WithContext(ctx) db = db.Model(&Chunk{}) db = db.Order("index desc") var latestChunk Chunk if err := db.First(&latestChunk).Error; err != nil { - return nil, fmt.Errorf("Chunk.GetLatestChunk error: %w", err) + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, fmt.Errorf("Chunk.getLatestChunk error: %w", err) } return &latestChunk, nil } @@ -105,15 +108,15 @@ func (o *Chunk) GetLatestChunk(ctx context.Context) (*Chunk, error) { // GetUnchunkedBlockHeight retrieves the first unchunked block number. func (o *Chunk) GetUnchunkedBlockHeight(ctx context.Context) (uint64, error) { // Get the latest chunk - latestChunk, err := o.GetLatestChunk(ctx) + latestChunk, err := o.getLatestChunk(ctx) if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - // if there is no chunk, return block number 1, - // because no need to chunk genesis block number - return 1, nil - } return 0, fmt.Errorf("Chunk.GetChunkedBlockHeight error: %w", err) } + if latestChunk == nil { + // if there is no chunk, return block number 1, + // because no need to chunk genesis block number + return 1, nil + } return latestChunk.EndBlockNumber + 1, nil } @@ -146,15 +149,15 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, dbTX ... var totalL1MessagePoppedBefore uint64 var parentChunkHash string var parentChunkStateRoot string - parentChunk, err := o.GetLatestChunk(ctx) - if err != nil && !errors.Is(errors.Unwrap(err), gorm.ErrRecordNotFound) { + parentChunk, err := o.getLatestChunk(ctx) + if err != nil { log.Error("failed to get latest chunk", "err", err) return nil, fmt.Errorf("Chunk.InsertChunk error: %w", err) } // if parentChunk==nil then err==gorm.ErrRecordNotFound, which means there's - // not chunk record in the db, we then use default empty values for the creating chunk; - // if parentChunk!=nil then err=nil, then we fill the parentChunk-related data into the creating chunk + // no chunk record in the db, we then use default empty values for the creating chunk; + // if parentChunk!=nil then err==nil, then we fill the parentChunk-related data into the creating chunk if parentChunk != nil { chunkIndex = parentChunk.Index + 1 totalL1MessagePoppedBefore = parentChunk.TotalL1MessagesPoppedBefore + parentChunk.TotalL1MessagesPoppedInChunk diff --git a/rollup/internal/orm/orm_test.go b/rollup/internal/orm/orm_test.go index 58391e2e5..dc458a0b3 100644 --- a/rollup/internal/orm/orm_test.go +++ b/rollup/internal/orm/orm_test.go @@ -234,10 +234,6 @@ func TestBatchOrm(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1}, - StartChunkIndex: 0, - StartChunkHash: chunkHash1, - EndChunkIndex: 0, - EndChunkHash: chunkHash1, } batch1, err := batchOrm.InsertBatch(context.Background(), batch) assert.NoError(t, err) @@ -255,10 +251,6 @@ func TestBatchOrm(t *testing.T) { TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk1}, - StartChunkIndex: 1, - StartChunkHash: chunkHash2, - EndChunkIndex: 1, - EndChunkHash: chunkHash2, } batch2, err := batchOrm.InsertBatch(context.Background(), batch) assert.NoError(t, err) diff --git a/rollup/tests/gas_oracle_test.go b/rollup/tests/gas_oracle_test.go index 2442ee775..c25e5eb54 100644 --- a/rollup/tests/gas_oracle_test.go +++ b/rollup/tests/gas_oracle_test.go @@ -12,7 +12,6 @@ import ( "scroll-tech/common/database" "scroll-tech/common/types" "scroll-tech/common/types/encoding" - "scroll-tech/common/types/encoding/codecv0" "scroll-tech/rollup/internal/controller/relayer" "scroll-tech/rollup/internal/controller/watcher" @@ -88,20 +87,11 @@ func testImportL2GasPrice(t *testing.T) { }, }, } - daChunk, err := codecv0.NewDAChunk(chunk, 0) - assert.NoError(t, err) - chunkHash, err := daChunk.Hash() - assert.NoError(t, err) - batch := &encoding.Batch{ Index: 0, TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - StartChunkHash: chunkHash, - EndChunkIndex: 0, - EndChunkHash: chunkHash, } batchOrm := orm.NewBatch(db) diff --git a/tests/integration-test/integration_test.go b/tests/integration-test/integration_test.go index f36ea7370..16455fc72 100644 --- a/tests/integration-test/integration_test.go +++ b/tests/integration-test/integration_test.go @@ -22,7 +22,6 @@ import ( "scroll-tech/common/database" "scroll-tech/common/docker" "scroll-tech/common/types/encoding" - "scroll-tech/common/types/encoding/codecv0" "scroll-tech/common/utils" "scroll-tech/common/version" @@ -93,22 +92,11 @@ func TestCoordinatorProverInteraction(t *testing.T) { RowConsumption: &gethTypes.RowConsumption{}, } chunk := &encoding.Chunk{Blocks: []*encoding.Block{block}} - - daChunk, err := codecv0.NewDAChunk(chunk, 0) - assert.NoError(t, err) - - daChunkHash, err := daChunk.Hash() - assert.NoError(t, err) - batch := &encoding.Batch{ Index: 0, TotalL1MessagePoppedBefore: 0, ParentBatchHash: common.Hash{}, Chunks: []*encoding.Chunk{chunk}, - StartChunkIndex: 0, - EndChunkIndex: 0, - StartChunkHash: daChunkHash, - EndChunkHash: daChunkHash, } err = l2BlockOrm.InsertL2Blocks(context.Background(), []*encoding.Block{block}) diff --git a/tests/integration-test/orm/batch.go b/tests/integration-test/orm/batch.go index 3abe064da..e173e3a11 100644 --- a/tests/integration-test/orm/batch.go +++ b/tests/integration-test/orm/batch.go @@ -73,6 +73,9 @@ func (o *Batch) GetLatestBatch(ctx context.Context) (*Batch, error) { var latestBatch Batch if err := db.First(&latestBatch).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } return nil, fmt.Errorf("Batch.GetLatestBatch error: %w", err) } return &latestBatch, nil @@ -85,21 +88,73 @@ func (o *Batch) InsertBatch(ctx context.Context, batch *encoding.Batch, dbTX ... return nil, errors.New("invalid args: batch is nil") } + numChunks := uint64(len(batch.Chunks)) + if numChunks == 0 { + return nil, errors.New("invalid args: batch contains 0 chunk") + } + daBatch, err := codecv0.NewDABatch(batch) if err != nil { log.Error("failed to create new DA batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, - "parent hash", batch.ParentBatchHash, "number of chunks", len(batch.Chunks), "err", err) + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) return nil, err } + var startChunkIndex uint64 + parentBatch, err := o.GetLatestBatch(ctx) + if err != nil { + log.Error("failed to get latest batch", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + // if parentBatch==nil then err==gorm.ErrRecordNotFound, which means there's + // no batch record in the db, we then use default empty values for the creating batch; + // if parentBatch!=nil then err==nil, then we fill the parentBatch-related data into the creating batch + if parentBatch != nil { + startChunkIndex = parentBatch.EndChunkIndex + 1 + } + + startDAChunk, err := codecv0.NewDAChunk(batch.Chunks[0], batch.TotalL1MessagePoppedBefore) + if err != nil { + log.Error("failed to create start DA chunk", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + startDAChunkHash, err := startDAChunk.Hash() + if err != nil { + log.Error("failed to get start DA chunk hash", "index", batch.Index, "total l1 message popped before", batch.TotalL1MessagePoppedBefore, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + totalL1MessagePoppedBeforeEndDAChunk := batch.TotalL1MessagePoppedBefore + for i := uint64(0); i < numChunks-1; i++ { + totalL1MessagePoppedBeforeEndDAChunk += batch.Chunks[i].NumL1Messages(totalL1MessagePoppedBeforeEndDAChunk) + } + endDAChunk, err := codecv0.NewDAChunk(batch.Chunks[numChunks-1], totalL1MessagePoppedBeforeEndDAChunk) + if err != nil { + log.Error("failed to create end DA chunk", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + + endDAChunkHash, err := endDAChunk.Hash() + if err != nil { + log.Error("failed to get end DA chunk hash", "index", batch.Index, "total l1 message popped before", totalL1MessagePoppedBeforeEndDAChunk, + "parent hash", batch.ParentBatchHash, "number of chunks", numChunks, "err", err) + return nil, fmt.Errorf("Batch.InsertBatch error: %w", err) + } + newBatch := Batch{ Index: batch.Index, Hash: daBatch.Hash().Hex(), - StartChunkHash: batch.StartChunkHash.Hex(), - StartChunkIndex: batch.StartChunkIndex, - EndChunkHash: batch.EndChunkHash.Hex(), - EndChunkIndex: batch.EndChunkIndex, + StartChunkHash: startDAChunkHash.Hex(), + StartChunkIndex: startChunkIndex, + EndChunkHash: endDAChunkHash.Hex(), + EndChunkIndex: startChunkIndex + numChunks - 1, StateRoot: batch.StateRoot().Hex(), WithdrawRoot: batch.WithdrawRoot().Hex(), ParentBatchHash: batch.ParentBatchHash.Hex(), diff --git a/tests/integration-test/orm/chunk.go b/tests/integration-test/orm/chunk.go index 69158d59c..eee6b267d 100644 --- a/tests/integration-test/orm/chunk.go +++ b/tests/integration-test/orm/chunk.go @@ -63,15 +63,18 @@ func (*Chunk) TableName() string { return "chunk" } -// GetLatestChunk retrieves the latest chunk from the database. -func (o *Chunk) GetLatestChunk(ctx context.Context) (*Chunk, error) { +// getLatestChunk retrieves the latest chunk from the database. +func (o *Chunk) getLatestChunk(ctx context.Context) (*Chunk, error) { db := o.db.WithContext(ctx) db = db.Model(&Chunk{}) db = db.Order("index desc") var latestChunk Chunk if err := db.First(&latestChunk).Error; err != nil { - return nil, fmt.Errorf("Chunk.GetLatestChunk error: %w", err) + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, fmt.Errorf("Chunk.getLatestChunk error: %w", err) } return &latestChunk, nil } @@ -87,15 +90,15 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *encoding.Chunk, dbTX ... var totalL1MessagePoppedBefore uint64 var parentChunkHash string var parentChunkStateRoot string - parentChunk, err := o.GetLatestChunk(ctx) - if err != nil && !errors.Is(errors.Unwrap(err), gorm.ErrRecordNotFound) { + parentChunk, err := o.getLatestChunk(ctx) + if err != nil { log.Error("failed to get latest chunk", "err", err) return nil, fmt.Errorf("Chunk.InsertChunk error: %w", err) } // if parentChunk==nil then err==gorm.ErrRecordNotFound, which means there's - // not chunk record in the db, we then use default empty values for the creating chunk; - // if parentChunk!=nil then err=nil, then we fill the parentChunk-related data into the creating chunk + // no chunk record in the db, we then use default empty values for the creating chunk; + // if parentChunk!=nil then err==nil, then we fill the parentChunk-related data into the creating chunk if parentChunk != nil { chunkIndex = parentChunk.Index + 1 totalL1MessagePoppedBefore = parentChunk.TotalL1MessagesPoppedBefore + parentChunk.TotalL1MessagesPoppedInChunk