diff --git a/rollup/tests/bridge_test.go b/rollup/tests/bridge_test.go index b0b9f86a8b..991961af5d 100644 --- a/rollup/tests/bridge_test.go +++ b/rollup/tests/bridge_test.go @@ -206,11 +206,8 @@ func TestFunction(t *testing.T) { // l1 rollup and watch rollup events t.Run("TestCommitAndFinalizeGenesisBatch", testCommitAndFinalizeGenesisBatch) - t.Run("TestCommitBatchAndFinalizeBatch", testCommitBatchAndFinalizeBatch) - t.Run("TestCommitBatchAndFinalizeBatch4844", testCommitBatchAndFinalizeBatch4844) - t.Run("TestCommitBatchAndFinalizeBatchBeforeAndAfter4844", testCommitBatchAndFinalizeBatchBeforeAndAfter4844) - t.Run("TestCommitBatchAndFinalizeBatchBeforeAndAfterCompression", testCommitBatchAndFinalizeBatchBeforeAndAfterCompression) - t.Run("TestCommitTwoBatchesAndFinalizeByOneBundle", testCommitTwoBatchesAndFinalizeByOneBundle) + t.Run("testCommitBatchAndFinalizeBatchOrBundleWithAllCodecVersions", testCommitBatchAndFinalizeBatchOrBundleWithAllCodecVersions) + t.Run("TestCommitBatchAndFinalizeBatchOrBundleCrossingAllTransitions", testCommitBatchAndFinalizeBatchOrBundleCrossingAllTransitions) // l1/l2 gas oracle t.Run("TestImportL1GasPrice", testImportL1GasPrice) diff --git a/rollup/tests/rollup_test.go b/rollup/tests/rollup_test.go index 136a276927..efc5c1adc9 100644 --- a/rollup/tests/rollup_test.go +++ b/rollup/tests/rollup_test.go @@ -2,6 +2,7 @@ package tests import ( "context" + "fmt" "math" "math/big" "testing" @@ -52,142 +53,26 @@ func testCommitAndFinalizeGenesisBatch(t *testing.T) { assert.Equal(t, types.RollupFinalized, types.RollupStatus(batch.RollupStatus)) } -func testCommitBatchAndFinalizeBatch(t *testing.T) { - db := setupDB(t) - defer database.CloseDB(db) - - prepareContracts(t) - - // Create L2Relayer - l2Cfg := rollupApp.Config.L2Config - l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig, ¶ms.ChainConfig{}, true, relayer.ServiceTypeL2RollupRelayer, nil) - assert.NoError(t, err) - defer l2Relayer.StopSenders() - - // add some blocks to db - var blocks []*encoding.Block - for i := int64(0); i < 10; i++ { - header := gethTypes.Header{ - Number: big.NewInt(i + 1), - ParentHash: common.Hash{}, - Difficulty: big.NewInt(0), - BaseFee: big.NewInt(0), - Root: common.HexToHash("0x1"), - } - blocks = append(blocks, &encoding.Block{ - Header: &header, - Transactions: nil, - WithdrawRoot: common.HexToHash("0x2"), - RowConsumption: &gethTypes.RowConsumption{}, - }) - } - - l2BlockOrm := orm.NewL2Block(db) - err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks) - assert.NoError(t, err) - - cp := watcher.NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ - MaxBlockNumPerChunk: 100, - MaxTxNumPerChunk: 10000, - MaxL1CommitGasPerChunk: 50000000000, - MaxL1CommitCalldataSizePerChunk: 1000000, - MaxRowConsumptionPerChunk: 1048319, - ChunkTimeoutSec: 300, - }, ¶ms.ChainConfig{}, db, nil) - - bp := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - MaxL1CommitGasPerBatch: 50000000000, - MaxL1CommitCalldataSizePerBatch: 1000000, - BatchTimeoutSec: 300, - }, ¶ms.ChainConfig{}, db, nil) - - cp.TryProposeChunk() - - batchOrm := orm.NewBatch(db) - unbatchedChunkIndex, err := batchOrm.GetFirstUnbatchedChunkIndex(context.Background()) - assert.NoError(t, err) - - chunkOrm := orm.NewChunk(db) - chunks, err := chunkOrm.GetChunksGEIndex(context.Background(), unbatchedChunkIndex, 0) - assert.NoError(t, err) - assert.Len(t, chunks, 1) - - bp.TryProposeBatch() - - l2Relayer.ProcessPendingBatches() - batch, err := batchOrm.GetLatestBatch(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, batch) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupCommitted == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetLatestBatch(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.CommitTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.CommitTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - - // add dummy proof - proof := &message.BatchProof{ - Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - } - err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, proof, 100) - assert.NoError(t, err) - err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) - assert.NoError(t, err) - - // process committed batch and check status - l2Relayer.ProcessCommittedBatches() - - statuses, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - assert.NoError(t, err) - assert.Equal(t, 1, len(statuses)) - assert.Equal(t, types.RollupFinalizing, statuses[0]) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupFinalized == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetLatestBatch(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.FinalizeTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) -} - -func testCommitBatchAndFinalizeBatch4844(t *testing.T) { - compressionTests := []bool{false, true} // false for uncompressed, true for compressed - for _, compressed := range compressionTests { +func testCommitBatchAndFinalizeBatchOrBundleWithAllCodecVersions(t *testing.T) { + codecVersions := []encoding.CodecVersion{encoding.CodecV0, encoding.CodecV1, encoding.CodecV2, encoding.CodecV3} + for _, codecVersion := range codecVersions { db := setupDB(t) prepareContracts(t) - // Create L2Relayer - l2Cfg := rollupApp.Config.L2Config var chainConfig *params.ChainConfig - if compressed { + if codecVersion == encoding.CodecV0 { + chainConfig = ¶ms.ChainConfig{} + } else if codecVersion == encoding.CodecV1 { + chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0)} + } else if codecVersion == encoding.CodecV2 { chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(0)} } else { - chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0)} + chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(0), DarwinTime: new(uint64)} } + + // Create L2Relayer + l2Cfg := rollupApp.Config.L2Config l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig, chainConfig, true, relayer.ServiceTypeL2RollupRelayer, nil) assert.NoError(t, err) @@ -209,232 +94,138 @@ func testCommitBatchAndFinalizeBatch4844(t *testing.T) { }) } - l2BlockOrm := orm.NewL2Block(db) - err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks) - assert.NoError(t, err) - cp := watcher.NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ MaxBlockNumPerChunk: 100, MaxTxNumPerChunk: 10000, - MaxL1CommitGasPerChunk: 1, - MaxL1CommitCalldataSizePerChunk: 100000, + MaxL1CommitGasPerChunk: 50000000000, + MaxL1CommitCalldataSizePerChunk: 1000000, MaxRowConsumptionPerChunk: 1048319, ChunkTimeoutSec: 300, MaxUncompressedBatchBytesSize: math.MaxUint64, }, chainConfig, db, nil) - bp := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - MaxL1CommitGasPerBatch: 1, - MaxL1CommitCalldataSizePerBatch: 100000, + bap := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ + MaxL1CommitGasPerBatch: 50000000000, + MaxL1CommitCalldataSizePerBatch: 1000000, BatchTimeoutSec: 300, MaxUncompressedBatchBytesSize: math.MaxUint64, }, chainConfig, db, nil) - cp.TryProposeChunk() + bup := watcher.NewBundleProposer(context.Background(), &config.BundleProposerConfig{ + MaxBatchNumPerBundle: 1000000, + BundleTimeoutSec: 300, + }, chainConfig, db, nil) - batchOrm := orm.NewBatch(db) - unbatchedChunkIndex, err := batchOrm.GetFirstUnbatchedChunkIndex(context.Background()) + l2BlockOrm := orm.NewL2Block(db) + err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks[:5]) assert.NoError(t, err) - chunkOrm := orm.NewChunk(db) - chunks, err := chunkOrm.GetChunksGEIndex(context.Background(), unbatchedChunkIndex, 0) + cp.TryProposeChunk() + bap.TryProposeBatch() + + err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks[5:]) assert.NoError(t, err) - assert.Len(t, chunks, 1) - bp.TryProposeBatch() + cp.TryProposeChunk() + bap.TryProposeBatch() + + bup.TryProposeBundle() // The proposed bundle contains two batches when codec version is codecv3. l2Relayer.ProcessPendingBatches() - batch, err := batchOrm.GetLatestBatch(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, batch) - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupCommitted == statuses[0] - }, 30*time.Second, time.Second) + batchOrm := orm.NewBatch(db) + bundleOrm := orm.NewBundle(db) assert.Eventually(t, func() bool { - batch, err = batchOrm.GetLatestBatch(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.CommitTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.CommitTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful + batches, getErr := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) + assert.NoError(t, getErr) + assert.Len(t, batches, 3) + batches = batches[1:] + for _, batch := range batches { + if types.RollupCommitted != types.RollupStatus(batch.RollupStatus) { + return false + } + } + return true }, 30*time.Second, time.Second) - // add dummy proof - proof := &message.BatchProof{ + batchProof := &message.BatchProof{ Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, } - err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, proof, 100) - assert.NoError(t, err) - err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) - assert.NoError(t, err) - - // process committed batch and check status - l2Relayer.ProcessCommittedBatches() - - statuses, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - assert.Equal(t, 1, len(statuses)) - assert.Equal(t, types.RollupFinalizing, statuses[0]) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupFinalized == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetLatestBatch(context.Background()) + batches = batches[1:] + for _, batch := range batches { + err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, batchProof, 100) + assert.NoError(t, err) + err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.FinalizeTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - - l2Relayer.StopSenders() - database.CloseDB(db) - } -} - -func testCommitBatchAndFinalizeBatchBeforeAndAfter4844(t *testing.T) { - compressionTests := []bool{false, true} // false for uncompressed, true for compressed - for _, compressed := range compressionTests { - db := setupDB(t) - - prepareContracts(t) - - // Create L2Relayer - l2Cfg := rollupApp.Config.L2Config - var chainConfig *params.ChainConfig - if compressed { - chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(5), CurieBlock: big.NewInt(5)} - } else { - chainConfig = ¶ms.ChainConfig{BernoulliBlock: big.NewInt(5)} } - l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig, chainConfig, true, relayer.ServiceTypeL2RollupRelayer, nil) - assert.NoError(t, err) - // add some blocks to db - var blocks []*encoding.Block - for i := int64(0); i < 10; i++ { - header := gethTypes.Header{ - Number: big.NewInt(i + 1), - ParentHash: common.Hash{}, - Difficulty: big.NewInt(0), - BaseFee: big.NewInt(0), - Root: common.HexToHash("0x1"), - } - blocks = append(blocks, &encoding.Block{ - Header: &header, - Transactions: nil, - WithdrawRoot: common.HexToHash("0x2"), - RowConsumption: &gethTypes.RowConsumption{}, - }) + bundleProof := &message.BundleProof{ + Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, } - - l2BlockOrm := orm.NewL2Block(db) - err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks) + bundles, err := bundleOrm.GetBundles(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - - cp := watcher.NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ - MaxBlockNumPerChunk: 100, - MaxTxNumPerChunk: 10000, - MaxL1CommitGasPerChunk: 50000000000, - MaxL1CommitCalldataSizePerChunk: 1000000, - MaxRowConsumptionPerChunk: 1048319, - ChunkTimeoutSec: 300, - MaxUncompressedBatchBytesSize: math.MaxUint64, - }, chainConfig, db, nil) - - bp := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - MaxL1CommitGasPerBatch: 50000000000, - MaxL1CommitCalldataSizePerBatch: 1000000, - BatchTimeoutSec: 300, - MaxUncompressedBatchBytesSize: math.MaxUint64, - }, chainConfig, db, nil) - - cp.TryProposeChunk() - cp.TryProposeChunk() - bp.TryProposeBatch() - bp.TryProposeBatch() - - for i := uint64(0); i < 2; i++ { - l2Relayer.ProcessPendingBatches() - batchOrm := orm.NewBatch(db) - batch, err := batchOrm.GetBatchByIndex(context.Background(), i+1) + for _, bundle := range bundles { + err = bundleOrm.UpdateProofAndProvingStatusByHash(context.Background(), bundle.Hash, bundleProof, types.ProvingTaskVerified, 100) assert.NoError(t, err) - assert.NotNil(t, batch) + } - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupCommitted == statuses[0] - }, 30*time.Second, time.Second) + assert.Eventually(t, func() bool { + l2Relayer.ProcessCommittedBatches() + l2Relayer.ProcessPendingBundles() - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetBatchByIndex(context.Background(), i+1) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.CommitTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.CommitTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - - // add dummy proof - proof := &message.BatchProof{ - Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - } - err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, proof, 100) - assert.NoError(t, err) - err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) + assert.Len(t, batches, 3) + batches = batches[1:] + for _, batch := range batches { + if types.RollupStatus(batch.RollupStatus) != types.RollupFinalized { + return false + } - // process committed batch and check status - l2Relayer.ProcessCommittedBatches() + assert.NotEmpty(t, batch.FinalizeTxHash) + receipt, getErr := l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) + assert.NoError(t, getErr) + assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) + } - statuses, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) + bundles, err := bundleOrm.GetBundles(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - assert.Equal(t, 1, len(statuses)) - assert.Equal(t, types.RollupFinalizing, statuses[0]) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupFinalized == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetBatchByIndex(context.Background(), i+1) + if codecVersion == encoding.CodecV0 || codecVersion == encoding.CodecV1 || codecVersion == encoding.CodecV2 { + assert.Len(t, bundles, 0) + } else { + assert.Len(t, bundles, 1) + bundle := bundles[0] + if types.RollupStatus(bundle.RollupStatus) != types.RollupFinalized { + return false + } + assert.NotEmpty(t, bundle.FinalizeTxHash) + receipt, err := l1Client.TransactionReceipt(context.Background(), common.HexToHash(bundle.FinalizeTxHash)) assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.FinalizeTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - } + assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{"bundle_hash": bundle.Hash}, nil, 0) + assert.NoError(t, err) + assert.Len(t, batches, 2) + for _, batch := range batches { + assert.Equal(t, batch.RollupStatus, bundle.RollupStatus) + assert.Equal(t, bundle.FinalizeTxHash, batch.FinalizeTxHash) + } + } + return true + }, 30*time.Second, time.Second) l2Relayer.StopSenders() database.CloseDB(db) } } -func testCommitBatchAndFinalizeBatchBeforeAndAfterCompression(t *testing.T) { +func testCommitBatchAndFinalizeBatchOrBundleCrossingAllTransitions(t *testing.T) { db := setupDB(t) defer database.CloseDB(db) @@ -442,7 +233,7 @@ func testCommitBatchAndFinalizeBatchBeforeAndAfterCompression(t *testing.T) { // Create L2Relayer l2Cfg := rollupApp.Config.L2Config - chainConfig := ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(5)} + chainConfig := ¶ms.ChainConfig{BernoulliBlock: big.NewInt(1), CurieBlock: big.NewInt(2), DarwinTime: func() *uint64 { t := uint64(4); return &t }()} l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig, chainConfig, true, relayer.ServiceTypeL2RollupRelayer, nil) assert.NoError(t, err) defer l2Relayer.StopSenders() @@ -456,6 +247,7 @@ func testCommitBatchAndFinalizeBatchBeforeAndAfterCompression(t *testing.T) { Difficulty: big.NewInt(0), BaseFee: big.NewInt(0), Root: common.HexToHash("0x1"), + Time: uint64(i + 1), } blocks = append(blocks, &encoding.Block{ Header: &header, @@ -479,122 +271,6 @@ func testCommitBatchAndFinalizeBatchBeforeAndAfterCompression(t *testing.T) { MaxUncompressedBatchBytesSize: math.MaxUint64, }, chainConfig, db, nil) - bp := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - MaxL1CommitGasPerBatch: 50000000000, - MaxL1CommitCalldataSizePerBatch: 1000000, - BatchTimeoutSec: 300, - MaxUncompressedBatchBytesSize: math.MaxUint64, - }, chainConfig, db, nil) - - cp.TryProposeChunk() - cp.TryProposeChunk() - bp.TryProposeBatch() - bp.TryProposeBatch() - - for i := uint64(0); i < 2; i++ { - l2Relayer.ProcessPendingBatches() - batchOrm := orm.NewBatch(db) - batch, err := batchOrm.GetBatchByIndex(context.Background(), i+1) - assert.NoError(t, err) - assert.NotNil(t, batch) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupCommitted == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetBatchByIndex(context.Background(), i+1) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.CommitTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.CommitTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - - // add dummy proof - proof := &message.BatchProof{ - Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - } - err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, proof, 100) - assert.NoError(t, err) - err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) - assert.NoError(t, err) - - // process committed batch and check status - l2Relayer.ProcessCommittedBatches() - - statuses, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - assert.NoError(t, err) - assert.Equal(t, 1, len(statuses)) - assert.Equal(t, types.RollupFinalizing, statuses[0]) - - // fetch rollup events - assert.Eventually(t, func() bool { - var statuses []types.RollupStatus - statuses, err = batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash}) - return err == nil && len(statuses) == 1 && types.RollupFinalized == statuses[0] - }, 30*time.Second, time.Second) - - assert.Eventually(t, func() bool { - batch, err = batchOrm.GetBatchByIndex(context.Background(), i+1) - assert.NoError(t, err) - assert.NotNil(t, batch) - assert.NotEmpty(t, batch.FinalizeTxHash) - var receipt *gethTypes.Receipt - receipt, err = l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) - return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful - }, 30*time.Second, time.Second) - } -} - -func testCommitTwoBatchesAndFinalizeByOneBundle(t *testing.T) { - db := setupDB(t) - defer database.CloseDB(db) - - prepareContracts(t) - - chainConfig := ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(0), DarwinTime: new(uint64)} - - // Create L2Relayer - l2Cfg := rollupApp.Config.L2Config - l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig, chainConfig, true, relayer.ServiceTypeL2RollupRelayer, nil) - assert.NoError(t, err) - defer l2Relayer.StopSenders() - - // add some blocks to db - var blocks []*encoding.Block - for i := int64(0); i < 10; i++ { - header := gethTypes.Header{ - Number: big.NewInt(i + 1), - ParentHash: common.Hash{}, - Difficulty: big.NewInt(0), - BaseFee: big.NewInt(0), - Root: common.HexToHash("0x1"), - } - blocks = append(blocks, &encoding.Block{ - Header: &header, - Transactions: nil, - WithdrawRoot: common.HexToHash("0x2"), - RowConsumption: &gethTypes.RowConsumption{}, - }) - } - - cp := watcher.NewChunkProposer(context.Background(), &config.ChunkProposerConfig{ - MaxBlockNumPerChunk: 100, - MaxTxNumPerChunk: 10000, - MaxL1CommitGasPerChunk: 50000000000, - MaxL1CommitCalldataSizePerChunk: 1000000, - MaxRowConsumptionPerChunk: 1048319, - ChunkTimeoutSec: 300, - MaxUncompressedBatchBytesSize: math.MaxUint64, - }, chainConfig, db, nil) - bap := watcher.NewBatchProposer(context.Background(), &config.BatchProposerConfig{ MaxL1CommitGasPerBatch: 50000000000, MaxL1CommitCalldataSizePerBatch: 1000000, @@ -607,70 +283,119 @@ func testCommitTwoBatchesAndFinalizeByOneBundle(t *testing.T) { BundleTimeoutSec: 300, }, chainConfig, db, nil) - l2BlockOrm := orm.NewL2Block(db) - err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks[:5]) - assert.NoError(t, err) - cp.TryProposeChunk() - bap.TryProposeBatch() - - err = l2BlockOrm.InsertL2Blocks(context.Background(), blocks[5:]) - assert.NoError(t, err) - cp.TryProposeChunk() + cp.TryProposeChunk() + cp.TryProposeChunk() + cp.TryProposeChunk() + + bap.TryProposeBatch() + bap.TryProposeBatch() + bap.TryProposeBatch() bap.TryProposeBatch() - bup.TryProposeBundle() // The proposed bundle contains two batches. + bup.TryProposeBundle() l2Relayer.ProcessPendingBatches() - // add dummy proof - proof := &message.BundleProof{ + batchOrm := orm.NewBatch(db) + bundleOrm := orm.NewBundle(db) + + assert.Eventually(t, func() bool { + batches, getErr := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) + assert.NoError(t, getErr) + assert.Len(t, batches, 4) + batches = batches[1:] + for _, batch := range batches { + fmt.Println("batch info", "start chunk index", batch.StartChunkIndex, "end chunk index", batch.EndChunkIndex, "batch.RollupStatus", batch.RollupStatus) + if types.RollupCommitted != types.RollupStatus(batch.RollupStatus) { + return false + } + } + return true + }, 30*time.Second, time.Second) + + batchProof := &message.BatchProof{ Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, } + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) + assert.NoError(t, err) + batches = batches[1:] + for _, batch := range batches { + err = batchOrm.UpdateProofByHash(context.Background(), batch.Hash, batchProof, 600) + assert.NoError(t, err) + err = batchOrm.UpdateProvingStatus(context.Background(), batch.Hash, types.ProvingTaskVerified) + assert.NoError(t, err) + } - bundleOrm := orm.NewBundle(db) + bundleProof := &message.BundleProof{ + Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + Instances: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + Vk: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + } bundles, err := bundleOrm.GetBundles(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - assert.Len(t, bundles, 1) - err = bundleOrm.UpdateProofAndProvingStatusByHash(context.Background(), bundles[0].Hash, proof, types.ProvingTaskVerified, 100) - assert.NoError(t, err) + for _, bundle := range bundles { + err = bundleOrm.UpdateProofAndProvingStatusByHash(context.Background(), bundle.Hash, bundleProof, types.ProvingTaskVerified, 100) + assert.NoError(t, err) + } assert.Eventually(t, func() bool { - batchOrm := orm.NewBatch(db) + l2Relayer.ProcessCommittedBatches() + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - assert.Len(t, batches, 3) - return types.RollupCommitted == types.RollupStatus(batches[1].RollupStatus) && types.RollupCommitted == types.RollupStatus(batches[2].RollupStatus) + assert.Len(t, batches, 4) + batches = batches[1:2] + for _, batch := range batches { + if types.RollupStatus(batch.RollupStatus) != types.RollupFinalized { + return false + } + assert.NotEmpty(t, batch.FinalizeTxHash) + receipt, getErr := l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) + assert.NoError(t, getErr) + assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) + } + return true }, 30*time.Second, time.Second) - // process pending bundle and check status - l2Relayer.ProcessPendingBundles() - - // fetch rollup events assert.Eventually(t, func() bool { - batchOrm := orm.NewBatch(db) + l2Relayer.ProcessPendingBundles() + batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) - assert.Len(t, batches, 3) - batches = batches[1:] - if types.RollupFinalized != types.RollupStatus(batches[0].RollupStatus) || types.RollupFinalized != types.RollupStatus(batches[1].RollupStatus) { - return false + assert.Len(t, batches, 4) + batches = batches[3:] + for _, batch := range batches { + if types.RollupStatus(batch.RollupStatus) != types.RollupFinalized { + return false + } + assert.NotEmpty(t, batch.FinalizeTxHash) + receipt, getErr := l1Client.TransactionReceipt(context.Background(), common.HexToHash(batch.FinalizeTxHash)) + assert.NoError(t, getErr) + assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) } - assert.NotEmpty(t, batches[0].FinalizeTxHash) - assert.Equal(t, batches[0].FinalizeTxHash, batches[1].FinalizeTxHash) - receipt, err := l1Client.TransactionReceipt(context.Background(), common.HexToHash(batches[0].FinalizeTxHash)) - assert.NoError(t, err) - assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) + bundles, err := bundleOrm.GetBundles(context.Background(), map[string]interface{}{}, nil, 0) assert.NoError(t, err) assert.Len(t, bundles, 1) - if types.RollupFinalized != types.RollupStatus(bundles[0].RollupStatus) { + bundle := bundles[0] + if types.RollupStatus(bundle.RollupStatus) != types.RollupFinalized { return false } - assert.Equal(t, batches[0].FinalizeTxHash, bundles[0].FinalizeTxHash) + assert.NotEmpty(t, bundle.FinalizeTxHash) + receipt, err := l1Client.TransactionReceipt(context.Background(), common.HexToHash(bundle.FinalizeTxHash)) + assert.NoError(t, err) + assert.Equal(t, gethTypes.ReceiptStatusSuccessful, receipt.Status) + batches, err = batchOrm.GetBatches(context.Background(), map[string]interface{}{"bundle_hash": bundle.Hash}, nil, 0) + assert.NoError(t, err) + assert.Len(t, batches, 1) + for _, batch := range batches { + assert.Equal(t, batch.RollupStatus, bundle.RollupStatus) + assert.Equal(t, bundle.FinalizeTxHash, batch.FinalizeTxHash) + } return true }, 30*time.Second, time.Second) }