From c34340ad8a0f0920c0b260c7c0d4049855e1cb18 Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:21:00 +0200 Subject: [PATCH 1/7] import cdk-validium-node genesis improvement --- cmd/run.go | 3 +- etherman/etherman.go | 44 ++++ state/block.go | 5 + .../common/syncinterfaces/etherman.go | 6 + synchronizer/synchronizer.go | 231 +++++++++++++----- 5 files changed, 229 insertions(+), 60 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 6da71dbd2d..ef15f56814 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -641,7 +641,8 @@ func forkIDIntervals(ctx context.Context, st *state.State, etherman *etherman.Cl if err != nil && !errors.Is(err, state.ErrStateNotSynchronized) { return []state.ForkIDInterval{}, fmt.Errorf("error checking lastL1BlockSynced. Error: %v", err) } - if lastBlock != nil { + // If lastBlock is below genesisBlock means state.ErrStateNotSynchronized (haven't started yet the sync process, is doing pregenesis sync) + if lastBlock != nil && lastBlock.BlockNumber >= genesisBlockNumber { log.Info("Getting forkIDs intervals. Please wait...") // Read Fork ID FROM POE SC forkIntervals, err := etherman.GetForks(ctx, genesisBlockNumber, lastBlock.BlockNumber) diff --git a/etherman/etherman.go b/etherman/etherman.go index 6f609fccc1..377d8b3519 100644 --- a/etherman/etherman.go +++ b/etherman/etherman.go @@ -41,6 +41,11 @@ import ( "golang.org/x/crypto/sha3" ) +const ( + // ETrogUpgradeVersion is the version of the LxLy upgrade + ETrogUpgradeVersion = 2 +) + var ( // Events RollupManager setBatchFeeSignatureHash = crypto.Keccak256Hash([]byte("SetBatchFee(uint256)")) @@ -339,6 +344,26 @@ func (etherMan *Client) VerifyGenBlockNumber(ctx context.Context, genBlockNumber return true, nil } +// GetL1BlockUpgradeLxLy It returns the block genesis for LxLy before genesisBlock or error +func (etherMan *Client) GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) { + it, err := etherMan.RollupManager.FilterInitialized(&bind.FilterOpts{ + Start: 1, + End: &genesisBlock, + Context: ctx, + }) + if err != nil { + return uint64(0), err + } + for it.Next() { + log.Debugf("BlockNumber: %d Topics:Initialized(%d)", it.Event.Raw.BlockNumber, it.Event.Version) + if it.Event.Version == ETrogUpgradeVersion { // 2 is ETROG (LxLy upgrade) + log.Infof("LxLy upgrade found at blockNumber: %d", it.Event.Raw.BlockNumber) + return it.Event.Raw.BlockNumber, nil + } + } + return uint64(0), ErrNotFound +} + // GetForks returns fork information func (etherMan *Client) GetForks(ctx context.Context, genBlockNumber uint64, lastL1BlockSynced uint64) ([]state.ForkIDInterval, error) { log.Debug("Getting forkIDs from blockNumber: ", genBlockNumber) @@ -470,6 +495,25 @@ func (etherMan *Client) GetRollupInfoByBlockRange(ctx context.Context, fromBlock return blocks, blocksOrder, nil } +// GetRollupInfoByBlockRangePreviousRollupGenesis function retrieves the Rollup information that are included in all this ethereum blocks +// but it only retrieves the information from the previous rollup genesis block to the current block. +func (etherMan *Client) GetRollupInfoByBlockRangePreviousRollupGenesis(ctx context.Context, fromBlock uint64, toBlock *uint64) ([]Block, map[common.Hash][]Order, error) { + // Filter query + query := ethereum.FilterQuery{ + FromBlock: new(big.Int).SetUint64(fromBlock), + Addresses: []common.Address{etherMan.l1Cfg.GlobalExitRootManagerAddr}, + Topics: [][]common.Hash{{updateL1InfoTreeSignatureHash}}, + } + if toBlock != nil { + query.ToBlock = new(big.Int).SetUint64(*toBlock) + } + blocks, blocksOrder, err := etherMan.readEvents(ctx, query) + if err != nil { + return nil, nil, err + } + return blocks, blocksOrder, nil +} + // Order contains the event order to let the synchronizer store the information following this order. type Order struct { Name EventOrder diff --git a/state/block.go b/state/block.go index 7883770249..8b91425bb3 100644 --- a/state/block.go +++ b/state/block.go @@ -1,6 +1,7 @@ package state import ( + "fmt" "time" "github.com/ethereum/go-ethereum/common" @@ -15,6 +16,10 @@ type Block struct { Checked bool } +func (b *Block) String() string { + return fmt.Sprintf("BlockNumber: %d, BlockHash: %s, ParentHash: %s, ReceivedAt: %s", b.BlockNumber, b.BlockHash, b.ParentHash, b.ReceivedAt) +} + // NewBlock creates a block with the given data. func NewBlock(blockNumber uint64) *Block { return &Block{BlockNumber: blockNumber} diff --git a/synchronizer/common/syncinterfaces/etherman.go b/synchronizer/common/syncinterfaces/etherman.go index fdbdd669f8..44717746df 100644 --- a/synchronizer/common/syncinterfaces/etherman.go +++ b/synchronizer/common/syncinterfaces/etherman.go @@ -20,8 +20,14 @@ type EthermanFullInterface interface { EthermanGetLatestBatchNumber GetFinalizedBlockNumber(ctx context.Context) (uint64, error) + EthermanPreRollup } type EthermanGetLatestBatchNumber interface { GetLatestBatchNumber() (uint64, error) } + +type EthermanPreRollup interface { + GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) + GetRollupInfoByBlockRangePreviousRollupGenesis(ctx context.Context, fromBlock uint64, toBlock *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error) +} diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index 75c3c3cefc..a193376caa 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -31,9 +31,10 @@ const ( // ParallelMode is the value for L1SynchronizationMode to run in parallel mode ParallelMode = "parallel" // SequentialMode is the value for L1SynchronizationMode to run in sequential mode - SequentialMode = "sequential" - maxBatchNumber = ^uint64(0) - timeOfLiveBatchOnCache = 5 * time.Minute + SequentialMode = "sequential" + maxBatchNumber = ^uint64(0) + timeOfLiveBatchOnCache = 5 * time.Minute + autoDiscoverLxLyBlockNumber = uint64(0) ) // Synchronizer connects L1 and L2 @@ -278,6 +279,162 @@ func rollback(ctx context.Context, dbTx pgx.Tx, err error) error { return err } +func (s *ClientSynchronizer) isGenesisProcessed(ctx context.Context, dbTx pgx.Tx) (bool, *state.Block, error) { + lastEthBlockSynced, err := s.state.GetLastBlock(ctx, dbTx) + if err != nil && errors.Is(err, state.ErrStateNotSynchronized) { + return false, lastEthBlockSynced, nil + } + + if lastEthBlockSynced.BlockNumber >= s.genesis.BlockNumber { + log.Infof("Genesis block processed. Last block synced: %d >= genesis %d", lastEthBlockSynced.BlockNumber, s.genesis.BlockNumber) + return true, lastEthBlockSynced, nil + } + log.Warnf("Genesis block not processed yet. Last block synced: %d < genesis %d", lastEthBlockSynced.BlockNumber, s.genesis.BlockNumber) + return false, lastEthBlockSynced, nil +} + +// getStartingL1Block find if need to update and if yes the starting point: +// bool -> need to process blocks +// uint64 -> first block to synchronize +// error -> error +// 1. First try to get last block on DB, if there are could be fully synced or pending blocks +// 2. If DB is empty the LxLy upgrade block as starting point +func (s *ClientSynchronizer) getStartingL1Block(ctx context.Context, genesisBlockNumber, rollupManagerBlockNumber uint64, dbTx pgx.Tx) (bool, uint64, error) { + lastBlock, err := s.state.GetLastBlock(ctx, dbTx) + if err != nil && errors.Is(err, state.ErrStateNotSynchronized) { + // No block on DB + upgradeLxLyBlockNumber := rollupManagerBlockNumber + if upgradeLxLyBlockNumber == autoDiscoverLxLyBlockNumber { + upgradeLxLyBlockNumber, err = s.etherMan.GetL1BlockUpgradeLxLy(ctx, genesisBlockNumber) + if err != nil && errors.Is(err, etherman.ErrNotFound) { + log.Infof("sync pregenesis: LxLy upgrade not detected before genesis block %d, it'll be sync as usual. Nothing to do yet", genesisBlockNumber) + return false, 0, nil + } else if err != nil { + log.Errorf("sync pregenesis: error getting LxLy upgrade block. Error: %v", err) + return false, 0, err + } + } + if rollupManagerBlockNumber >= genesisBlockNumber { + log.Infof("sync pregenesis: rollupManagerBlockNumber>=genesisBlockNumber (%d>=%d). Nothing in pregenesis", rollupManagerBlockNumber, genesisBlockNumber) + return false, 0, nil + } + log.Infof("sync pregenesis: No block on DB, starting from LxLy upgrade block (rollupManagerBlockNumber) %d", upgradeLxLyBlockNumber) + return true, upgradeLxLyBlockNumber, nil + } else if err != nil { + log.Errorf("Error getting last Block on DB err:%v", err) + return false, 0, err + } + if lastBlock.BlockNumber >= genesisBlockNumber-1 { + log.Warnf("sync pregenesis: Last block processed is %d, which is greater or equal than the previous genesis block %d", lastBlock, genesisBlockNumber) + return false, 0, nil + } + log.Infof("sync pregenesis: Continue processing pre-genesis blocks, last block processed on DB is %d", lastBlock.BlockNumber+1) + return true, lastBlock.BlockNumber + 1, nil +} + +func (s *ClientSynchronizer) synchronizePreGenesisRollupEvents(syncChunkSize uint64, ctx context.Context) error { + // Sync events from RollupManager that happen before rollup creation + startTime := time.Now() + log.Info("synchronizing events from RollupManager that happen before rollup creation") + rollupManagerBlockNumber := autoDiscoverLxLyBlockNumber + needToUpdate, fromBlock, err := s.getStartingL1Block(ctx, s.genesis.BlockNumber, rollupManagerBlockNumber, nil) + if err != nil { + log.Errorf("sync pregenesis: error getting starting L1 block. Error: %v", err) + return err + } + if !needToUpdate { + log.Infof("sync pregenesis: No need to process blocks before the genesis block %d", s.genesis.BlockNumber) + return nil + } + toBlockFinal := s.genesis.BlockNumber - 1 + log.Infof("sync pregenesis: starting syncing pre genesis LxLy events from block %d to block %d (total %d blocks) chunk size %d", + fromBlock, toBlockFinal, toBlockFinal-fromBlock+1, syncChunkSize) + for i := fromBlock; true; i += syncChunkSize { + toBlock := min(i+syncChunkSize-1, toBlockFinal) + log.Debugf("sync pregenesis: syncing L1InfoTree from blocks [%d - %d] remains: %d", i, toBlock, toBlockFinal-toBlock) + blocks, order, err := s.etherMan.GetRollupInfoByBlockRangePreviousRollupGenesis(s.ctx, i, &toBlock) + if err != nil { + log.Error("sync pregenesis: error getting rollupInfoByBlockRange before rollup genesis: ", err) + return err + } + log.Debugf("sync pregenesis: syncing L1InfoTree from blocks [%d - %d] -> num_block:%d num_order:%d", i, toBlock, len(blocks), len(order)) + err = s.ProcessBlockRange(blocks, order) + if err != nil { + log.Error("sync pregenesis: error processing blocks before the genesis: ", err) + return err + } + if toBlock == toBlockFinal { + break + } + } + elapsedTime := time.Since(startTime) + log.Infof("sync pregenesis: sync L1InfoTree finish: from %d to %d total_block %d done in %s", fromBlock, toBlockFinal, toBlockFinal-fromBlock+1, &elapsedTime) + return nil +} + +func (s *ClientSynchronizer) processGenesis() (*state.Block, error) { + log.Info("State is empty, verifying genesis block") + valid, err := s.etherMan.VerifyGenBlockNumber(s.ctx, s.genesis.BlockNumber) + if err != nil { + log.Error("error checking genesis block number. Error: ", err) + return nil, err + } else if !valid { + log.Error("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed") + return nil, fmt.Errorf("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed") + } + err = s.synchronizePreGenesisRollupEvents(s.cfg.SyncChunkSize, s.ctx) + if err != nil { + log.Error("error synchronizing pre genesis events: ", err) + return nil, err + } + + header, err := s.etherMan.HeaderByNumber(s.ctx, big.NewInt(0).SetUint64(s.genesis.BlockNumber)) + if err != nil { + log.Errorf("error getting l1 block header for block %d. Error: %v", s.genesis.BlockNumber, err) + return nil, err + } + log.Info("synchronizing rollup creation block") + lastEthBlockSynced := &state.Block{ + BlockNumber: header.Number.Uint64(), + BlockHash: header.Hash(), + ParentHash: header.ParentHash, + ReceivedAt: time.Unix(int64(header.Time), 0), + } + dbTx, err := s.state.BeginStateTransaction(s.ctx) + if err != nil { + log.Errorf("error creating db transaction to get latest block. Error: %v", err) + return nil, err + } + // This add the genesis block and set values on tree + genesisRoot, err := s.state.SetGenesis(s.ctx, *lastEthBlockSynced, s.genesis, stateMetrics.SynchronizerCallerLabel, dbTx) + if err != nil { + log.Error("error setting genesis: ", err) + return nil, rollback(s.ctx, dbTx, err) + } + err = s.RequestAndProcessRollupGenesisBlock(dbTx, lastEthBlockSynced) + if err != nil { + log.Error("error processing Rollup genesis block: ", err) + return nil, rollback(s.ctx, dbTx, err) + } + + if genesisRoot != s.genesis.Root { + log.Errorf("Calculated newRoot should be %s instead of %s", s.genesis.Root.String(), genesisRoot.String()) + return nil, rollback(s.ctx, dbTx, fmt.Errorf("calculated newRoot should be %s instead of %s", s.genesis.Root.String(), genesisRoot.String())) + } + // Waiting for the flushID to be stored + err = s.checkFlushID(dbTx) + if err != nil { + log.Error("error checking genesis flushID: ", err) + return nil, rollback(s.ctx, dbTx, err) + } + if err := dbTx.Commit(s.ctx); err != nil { + log.Errorf("error genesis committing dbTx, err: %v", err) + return nil, rollback(s.ctx, dbTx, err) + } + log.Info("Genesis root matches! Stored genesis blocks.") + return lastEthBlockSynced, nil +} + // Sync function will read the last state synced and will continue from that point. // Sync() will read blockchain events to detect rollup updates func (s *ClientSynchronizer) Sync() error { @@ -288,68 +445,24 @@ func (s *ClientSynchronizer) Sync() error { if s.asyncL1BlockChecker != nil { _ = s.asyncL1BlockChecker.OnStart(s.ctx) } - - dbTx, err := s.state.BeginStateTransaction(s.ctx) + genesisDone, lastEthBlockSynced, err := s.isGenesisProcessed(s.ctx, nil) if err != nil { - log.Errorf("error creating db transaction to get latest block. Error: %v", err) + log.Errorf("error checking if genesis is processed. Error: %v", err) return err } - lastEthBlockSynced, err := s.state.GetLastBlock(s.ctx, dbTx) - if err != nil { - if errors.Is(err, state.ErrStateNotSynchronized) { - log.Info("State is empty, verifying genesis block") - valid, err := s.etherMan.VerifyGenBlockNumber(s.ctx, s.genesis.BlockNumber) - if err != nil { - log.Error("error checking genesis block number. Error: ", err) - return rollback(s.ctx, dbTx, err) - } else if !valid { - log.Error("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed") - return rollback(s.ctx, dbTx, fmt.Errorf("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed")) - } - log.Info("Setting genesis block") - header, err := s.etherMan.HeaderByNumber(s.ctx, big.NewInt(0).SetUint64(s.genesis.BlockNumber)) - if err != nil { - log.Errorf("error getting l1 block header for block %d. Error: %v", s.genesis.BlockNumber, err) - return rollback(s.ctx, dbTx, err) - } - lastEthBlockSynced = &state.Block{ - BlockNumber: header.Number.Uint64(), - BlockHash: header.Hash(), - ParentHash: header.ParentHash, - ReceivedAt: time.Unix(int64(header.Time), 0), - } - genesisRoot, err := s.state.SetGenesis(s.ctx, *lastEthBlockSynced, s.genesis, stateMetrics.SynchronizerCallerLabel, dbTx) - if err != nil { - log.Error("error setting genesis: ", err) - return rollback(s.ctx, dbTx, err) - } - err = s.RequestAndProcessRollupGenesisBlock(dbTx, lastEthBlockSynced) - if err != nil { - log.Error("error processing Rollup genesis block: ", err) - return rollback(s.ctx, dbTx, err) - } - - if genesisRoot != s.genesis.Root { - log.Errorf("Calculated newRoot should be %s instead of %s", s.genesis.Root.String(), genesisRoot.String()) - return rollback(s.ctx, dbTx, fmt.Errorf("calculated newRoot should be %s instead of %s", s.genesis.Root.String(), genesisRoot.String())) - } - // Waiting for the flushID to be stored - err = s.checkFlushID(dbTx) - if err != nil { - log.Error("error checking genesis flushID: ", err) - return rollback(s.ctx, dbTx, err) - } - log.Debug("Genesis root matches!") - } else { - log.Error("unexpected error getting the latest ethereum block. Error: ", err) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) - return rollbackErr - } + if !genesisDone { + lastEthBlockSynced, err = s.processGenesis() + if err != nil { + log.Errorf("error processing genesis. Error: %v", err) return err } } + dbTx, err := s.state.BeginStateTransaction(s.ctx) + if err != nil { + log.Errorf("error creating db transaction to get latest block. Error: %v", err) + return err + } + initBatchNumber, err := s.state.GetLastBatchNumber(s.ctx, dbTx) if err != nil { log.Error("error getting latest batchNumber synced. Error: ", err) From fc3b945a2c66e0f8923d90c1e9f514bcda757add Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Mon, 2 Sep 2024 15:48:23 +0200 Subject: [PATCH 2/7] fix unitttest --- .../mocks/etherman_full_interface.go | 126 ++++++++++ synchronizer/synchronizer_test.go | 227 ++++++++++-------- 2 files changed, 259 insertions(+), 94 deletions(-) diff --git a/synchronizer/common/syncinterfaces/mocks/etherman_full_interface.go b/synchronizer/common/syncinterfaces/mocks/etherman_full_interface.go index a904419575..c6e99c36ac 100644 --- a/synchronizer/common/syncinterfaces/mocks/etherman_full_interface.go +++ b/synchronizer/common/syncinterfaces/mocks/etherman_full_interface.go @@ -143,6 +143,63 @@ func (_c *EthermanFullInterface_GetFinalizedBlockNumber_Call) RunAndReturn(run f return _c } +// GetL1BlockUpgradeLxLy provides a mock function with given fields: ctx, genesisBlock +func (_m *EthermanFullInterface) GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) { + ret := _m.Called(ctx, genesisBlock) + + if len(ret) == 0 { + panic("no return value specified for GetL1BlockUpgradeLxLy") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (uint64, error)); ok { + return rf(ctx, genesisBlock) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) uint64); ok { + r0 = rf(ctx, genesisBlock) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, genesisBlock) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EthermanFullInterface_GetL1BlockUpgradeLxLy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetL1BlockUpgradeLxLy' +type EthermanFullInterface_GetL1BlockUpgradeLxLy_Call struct { + *mock.Call +} + +// GetL1BlockUpgradeLxLy is a helper method to define mock.On call +// - ctx context.Context +// - genesisBlock uint64 +func (_e *EthermanFullInterface_Expecter) GetL1BlockUpgradeLxLy(ctx interface{}, genesisBlock interface{}) *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call { + return &EthermanFullInterface_GetL1BlockUpgradeLxLy_Call{Call: _e.mock.On("GetL1BlockUpgradeLxLy", ctx, genesisBlock)} +} + +func (_c *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call) Run(run func(ctx context.Context, genesisBlock uint64)) *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64)) + }) + return _c +} + +func (_c *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call) Return(_a0 uint64, _a1 error) *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call) RunAndReturn(run func(context.Context, uint64) (uint64, error)) *EthermanFullInterface_GetL1BlockUpgradeLxLy_Call { + _c.Call.Return(run) + return _c +} + // GetLatestBatchNumber provides a mock function with given fields: func (_m *EthermanFullInterface) GetLatestBatchNumber() (uint64, error) { ret := _m.Called() @@ -322,6 +379,75 @@ func (_c *EthermanFullInterface_GetRollupInfoByBlockRange_Call) RunAndReturn(run return _c } +// GetRollupInfoByBlockRangePreviousRollupGenesis provides a mock function with given fields: ctx, fromBlock, toBlock +func (_m *EthermanFullInterface) GetRollupInfoByBlockRangePreviousRollupGenesis(ctx context.Context, fromBlock uint64, toBlock *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error) { + ret := _m.Called(ctx, fromBlock, toBlock) + + if len(ret) == 0 { + panic("no return value specified for GetRollupInfoByBlockRangePreviousRollupGenesis") + } + + var r0 []etherman.Block + var r1 map[common.Hash][]etherman.Order + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error)); ok { + return rf(ctx, fromBlock, toBlock) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) []etherman.Block); ok { + r0 = rf(ctx, fromBlock, toBlock) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]etherman.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, *uint64) map[common.Hash][]etherman.Order); ok { + r1 = rf(ctx, fromBlock, toBlock) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(map[common.Hash][]etherman.Order) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64, *uint64) error); ok { + r2 = rf(ctx, fromBlock, toBlock) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRollupInfoByBlockRangePreviousRollupGenesis' +type EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call struct { + *mock.Call +} + +// GetRollupInfoByBlockRangePreviousRollupGenesis is a helper method to define mock.On call +// - ctx context.Context +// - fromBlock uint64 +// - toBlock *uint64 +func (_e *EthermanFullInterface_Expecter) GetRollupInfoByBlockRangePreviousRollupGenesis(ctx interface{}, fromBlock interface{}, toBlock interface{}) *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + return &EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call{Call: _e.mock.On("GetRollupInfoByBlockRangePreviousRollupGenesis", ctx, fromBlock, toBlock)} +} + +func (_c *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) Run(run func(ctx context.Context, fromBlock uint64, toBlock *uint64)) *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(*uint64)) + }) + return _c +} + +func (_c *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) Return(_a0 []etherman.Block, _a1 map[common.Hash][]etherman.Order, _a2 error) *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) RunAndReturn(run func(context.Context, uint64, *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error)) *EthermanFullInterface_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Return(run) + return _c +} + // GetTrustedSequencerURL provides a mock function with given fields: func (_m *EthermanFullInterface) GetTrustedSequencerURL() (string, error) { ret := _m.Called() diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index ce0c27e280..56c4184af0 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -123,7 +123,7 @@ func TestGivenPermissionlessNodeWhenSyncronizeFirstTimeABatchThenStoreItInALocal // but it used a feature that is not implemented in new one that is asking beyond the last block on L1 func TestForcedBatchEtrog(t *testing.T) { genesis := state.Genesis{ - BlockNumber: uint64(123456), + BlockNumber: uint64(0), } cfg := Config{ SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, @@ -156,15 +156,22 @@ func TestForcedBatchEtrog(t *testing.T) { ToBatchNumber: ^uint64(0), } m.State.EXPECT().GetForkIDInMemory(uint64(7)).Return(&forkIdInterval) + parentHash := common.HexToHash("0x111") + ethHeader := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} + ethBlock := ethTypes.NewBlockWithHeader(ethHeader) + lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64(), ParentHash: ethBlock.ParentHash()} + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethHeader0 := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethHeader1 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock0.Hash()} ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} @@ -176,7 +183,7 @@ func TestForcedBatchEtrog(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock0, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). @@ -246,13 +253,15 @@ func TestForcedBatchEtrog(t *testing.T) { }} ethermanBlock0 := etherman.Block{ - BlockNumber: 0, + BlockNumber: ethBlock0.NumberU64(), ReceivedAt: t, + ParentHash: ethBlock0.ParentHash(), BlockHash: ethBlock0.Hash(), } ethermanBlock1 := etherman.Block{ - BlockNumber: 1, + BlockNumber: ethBlock0.NumberU64(), ReceivedAt: t, + ParentHash: ethBlock1.ParentHash(), BlockHash: ethBlock1.Hash(), SequencedBatches: [][]etherman.SequencedBatch{{sequencedBatch}}, ForcedBatches: forceb, @@ -401,7 +410,7 @@ func TestForcedBatchEtrog(t *testing.T) { // but it used a feature that is not implemented in new one that is asking beyond the last block on L1 func TestSequenceForcedBatchIncaberry(t *testing.T) { genesis := state.Genesis{ - BlockNumber: uint64(123456), + BlockNumber: uint64(0), } cfg := Config{ SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, @@ -423,14 +432,24 @@ func TestSequenceForcedBatchIncaberry(t *testing.T) { // state preparation ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }) + + parentHash := common.HexToHash("0xb14c74e4dddf25627a745f46cae6ac98782e2783c3ccc28107c8210e60d58861") + ethHeader := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} + ethBlock := ethTypes.NewBlockWithHeader(ethHeader) + lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64(), ParentHash: ethBlock.ParentHash()} + + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock, nil). + Once() + m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethHeader0 := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethHeader1 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock0.Hash()} ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} @@ -442,7 +461,7 @@ func TestSequenceForcedBatchIncaberry(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock0, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). @@ -517,7 +536,7 @@ func TestSequenceForcedBatchIncaberry(t *testing.T) { ParentHash: ethBlock0.ParentHash(), } ethermanBlock1 := etherman.Block{ - BlockNumber: ethBlock1.NumberU64(), + BlockNumber: ethBlock0.NumberU64(), BlockHash: ethBlock1.Hash(), ParentHash: ethBlock1.ParentHash(), SequencedForceBatches: [][]etherman.SequencedForceBatch{{sequencedForceBatch}}, @@ -965,29 +984,34 @@ func TestReorg(t *testing.T) { ToBatchNumber: math.MaxUint64, } m.State.EXPECT().GetForkIDInMemory(uint64(9)).Return(&forkIdInterval) + parentHash := common.HexToHash("0x111") + ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) + ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} + ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) + ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} + ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) + ethHeader3bis := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2bis.Hash()} + ethBlock3bis := ethTypes.NewBlockWithHeader(ethHeader3bis) + ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) + ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} + ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) + ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} + ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) + + lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} + lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} + + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock1, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} - ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} - ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) - ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} - ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) - ethHeader3bis := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2bis.Hash()} - ethBlock3bis := ethTypes.NewBlockWithHeader(ethHeader3bis) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} - ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) - ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} - ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) - ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} - ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) - - lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} - lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} m.State. On("GetForkIDByBatchNumber", mock.Anything). @@ -996,7 +1020,7 @@ func TestReorg(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock1, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). @@ -1288,23 +1312,27 @@ func TestLatestSyncedBlockEmpty(t *testing.T) { ToBatchNumber: math.MaxUint64, } m.State.EXPECT().GetForkIDInMemory(uint64(9)).Return(&forkIdInterval) + parentHash := common.HexToHash("0x111") + ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) + ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) + ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} + ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) + ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} + ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) + + lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} + lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock1, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} - ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} - ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) - ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} - ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) - ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} - ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) - - lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} - lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} m.State. On("GetForkIDByBatchNumber", mock.Anything). @@ -1313,7 +1341,7 @@ func TestLatestSyncedBlockEmpty(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock1, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). @@ -1505,25 +1533,29 @@ func TestRegularReorg(t *testing.T) { ToBatchNumber: math.MaxUint64, } m.State.EXPECT().GetForkIDInMemory(uint64(9)).Return(&forkIdInterval) + parentHash := common.HexToHash("0x111") + ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) + ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} + ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) + ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} + ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) + ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) + ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} + ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) + + lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} + lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock1, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} - ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} - ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) - ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} - ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} - ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) - ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} - ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) - - lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} - lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} m.State. On("GetForkIDByBatchNumber", mock.Anything). @@ -1532,7 +1564,7 @@ func TestRegularReorg(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock1, nil). - Once() + Maybe() // After a ResetState get lastblock that must be block 0 m.State. @@ -1790,26 +1822,30 @@ func TestLatestSyncedBlockEmptyWithExtraReorg(t *testing.T) { ToBatchNumber: math.MaxUint64, } m.State.EXPECT().GetForkIDInMemory(uint64(9)).Return(&forkIdInterval) + parentHash := common.HexToHash("0x111") + ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) + ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) + ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 0, GasUsed: 10} + ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) + ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} + ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) + ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} + ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) + + lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} + lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} + lastBlock2 := &state.Block{BlockHash: ethBlock2.Hash(), BlockNumber: ethBlock2.Number().Uint64(), ParentHash: ethBlock2.ParentHash()} + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock2, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} - ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} - ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) - ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 0, GasUsed: 10} - ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) - ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} - ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) - ethHeader3 := ðTypes.Header{Number: big.NewInt(3), ParentHash: ethBlock2.Hash()} - ethBlock3 := ethTypes.NewBlockWithHeader(ethHeader3) - - lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} - lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} - lastBlock2 := &state.Block{BlockHash: ethBlock2.Hash(), BlockNumber: ethBlock2.Number().Uint64(), ParentHash: ethBlock2.ParentHash()} m.State. On("GetForkIDByBatchNumber", mock.Anything). @@ -1818,7 +1854,7 @@ func TestLatestSyncedBlockEmptyWithExtraReorg(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock2, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). @@ -1971,13 +2007,13 @@ func TestLatestSyncedBlockEmptyWithExtraReorg(t *testing.T) { Once() ethermanBlock0 := etherman.Block{ - BlockNumber: 0, + BlockNumber: ethBlock0.NumberU64(), ReceivedAt: ti, BlockHash: ethBlock0.Hash(), ParentHash: ethBlock0.ParentHash(), } ethermanBlock1bis := etherman.Block{ - BlockNumber: 1, + BlockNumber: ethBlock1.NumberU64(), ReceivedAt: ti, BlockHash: ethBlock1.Hash(), ParentHash: ethBlock1.ParentHash(), @@ -2069,25 +2105,28 @@ func TestCallFromEmptyBlockAndReorg(t *testing.T) { ToBatchNumber: math.MaxUint64, } m.State.EXPECT().GetForkIDInMemory(uint64(9)).Return(&forkIdInterval) - + parentHash := common.HexToHash("0x111") + ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} + ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) + ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} + ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) + ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} + ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) + ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} + ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) + ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} + ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) + + lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} + lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} + m.State. + On("GetLastBlock", mock.Anything, nil). + Return(lastBlock1, nil). + Once() m.State. On("BeginStateTransaction", ctxMatchBy). Run(func(args mock.Arguments) { ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader0 := ðTypes.Header{Number: big.NewInt(0), ParentHash: parentHash} - ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0) - ethHeader1bis := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash(), Time: 10, GasUsed: 20, Root: common.HexToHash("0x234")} - ethBlock1bis := ethTypes.NewBlockWithHeader(ethHeader1bis) - ethHeader2bis := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1bis.Hash()} - ethBlock2bis := ethTypes.NewBlockWithHeader(ethHeader2bis) - ethHeader1 := ðTypes.Header{Number: big.NewInt(1), ParentHash: ethBlock0.Hash()} - ethBlock1 := ethTypes.NewBlockWithHeader(ethHeader1) - ethHeader2 := ðTypes.Header{Number: big.NewInt(2), ParentHash: ethBlock1.Hash()} - ethBlock2 := ethTypes.NewBlockWithHeader(ethHeader2) - - lastBlock0 := &state.Block{BlockHash: ethBlock0.Hash(), BlockNumber: ethBlock0.Number().Uint64(), ParentHash: ethBlock0.ParentHash()} - lastBlock1 := &state.Block{BlockHash: ethBlock1.Hash(), BlockNumber: ethBlock1.Number().Uint64(), ParentHash: ethBlock1.ParentHash()} m.State. On("GetForkIDByBatchNumber", mock.Anything). @@ -2096,7 +2135,7 @@ func TestCallFromEmptyBlockAndReorg(t *testing.T) { m.State. On("GetLastBlock", ctx, m.DbTx). Return(lastBlock1, nil). - Once() + Maybe() m.State. On("GetLastBatchNumber", ctx, m.DbTx). From 30e1debf2649c4a543f098f06d5c78690f6625c9 Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:17:29 +0200 Subject: [PATCH 3/7] update comment --- cmd/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/run.go b/cmd/run.go index ef15f56814..bf48eabd65 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -641,7 +641,7 @@ func forkIDIntervals(ctx context.Context, st *state.State, etherman *etherman.Cl if err != nil && !errors.Is(err, state.ErrStateNotSynchronized) { return []state.ForkIDInterval{}, fmt.Errorf("error checking lastL1BlockSynced. Error: %v", err) } - // If lastBlock is below genesisBlock means state.ErrStateNotSynchronized (haven't started yet the sync process, is doing pregenesis sync) + // If there are a lastBlock and is >= to genesisBlock, means that have started the sync process (if not if lastBlock!=nil then is doing pregenesis sync) if lastBlock != nil && lastBlock.BlockNumber >= genesisBlockNumber { log.Info("Getting forkIDs intervals. Please wait...") // Read Fork ID FROM POE SC From de532322a589c4849f0e84f2a026da2394972049 Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Mon, 2 Sep 2024 18:17:07 +0200 Subject: [PATCH 4/7] add process genesis block --- .../mocks/etherman_pre_rollup.go | 166 ++++++++++++++++++ synchronizer/synchronizer.go | 147 ++++++++-------- 2 files changed, 240 insertions(+), 73 deletions(-) create mode 100644 synchronizer/common/syncinterfaces/mocks/etherman_pre_rollup.go diff --git a/synchronizer/common/syncinterfaces/mocks/etherman_pre_rollup.go b/synchronizer/common/syncinterfaces/mocks/etherman_pre_rollup.go new file mode 100644 index 0000000000..3599152aee --- /dev/null +++ b/synchronizer/common/syncinterfaces/mocks/etherman_pre_rollup.go @@ -0,0 +1,166 @@ +// Code generated by mockery. DO NOT EDIT. + +package mock_syncinterfaces + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + etherman "github.com/0xPolygonHermez/zkevm-node/etherman" + + mock "github.com/stretchr/testify/mock" +) + +// EthermanPreRollup is an autogenerated mock type for the EthermanPreRollup type +type EthermanPreRollup struct { + mock.Mock +} + +type EthermanPreRollup_Expecter struct { + mock *mock.Mock +} + +func (_m *EthermanPreRollup) EXPECT() *EthermanPreRollup_Expecter { + return &EthermanPreRollup_Expecter{mock: &_m.Mock} +} + +// GetL1BlockUpgradeLxLy provides a mock function with given fields: ctx, genesisBlock +func (_m *EthermanPreRollup) GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) { + ret := _m.Called(ctx, genesisBlock) + + if len(ret) == 0 { + panic("no return value specified for GetL1BlockUpgradeLxLy") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (uint64, error)); ok { + return rf(ctx, genesisBlock) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) uint64); ok { + r0 = rf(ctx, genesisBlock) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, genesisBlock) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EthermanPreRollup_GetL1BlockUpgradeLxLy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetL1BlockUpgradeLxLy' +type EthermanPreRollup_GetL1BlockUpgradeLxLy_Call struct { + *mock.Call +} + +// GetL1BlockUpgradeLxLy is a helper method to define mock.On call +// - ctx context.Context +// - genesisBlock uint64 +func (_e *EthermanPreRollup_Expecter) GetL1BlockUpgradeLxLy(ctx interface{}, genesisBlock interface{}) *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call { + return &EthermanPreRollup_GetL1BlockUpgradeLxLy_Call{Call: _e.mock.On("GetL1BlockUpgradeLxLy", ctx, genesisBlock)} +} + +func (_c *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call) Run(run func(ctx context.Context, genesisBlock uint64)) *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64)) + }) + return _c +} + +func (_c *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call) Return(_a0 uint64, _a1 error) *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call) RunAndReturn(run func(context.Context, uint64) (uint64, error)) *EthermanPreRollup_GetL1BlockUpgradeLxLy_Call { + _c.Call.Return(run) + return _c +} + +// GetRollupInfoByBlockRangePreviousRollupGenesis provides a mock function with given fields: ctx, fromBlock, toBlock +func (_m *EthermanPreRollup) GetRollupInfoByBlockRangePreviousRollupGenesis(ctx context.Context, fromBlock uint64, toBlock *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error) { + ret := _m.Called(ctx, fromBlock, toBlock) + + if len(ret) == 0 { + panic("no return value specified for GetRollupInfoByBlockRangePreviousRollupGenesis") + } + + var r0 []etherman.Block + var r1 map[common.Hash][]etherman.Order + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error)); ok { + return rf(ctx, fromBlock, toBlock) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) []etherman.Block); ok { + r0 = rf(ctx, fromBlock, toBlock) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]etherman.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, *uint64) map[common.Hash][]etherman.Order); ok { + r1 = rf(ctx, fromBlock, toBlock) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(map[common.Hash][]etherman.Order) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64, *uint64) error); ok { + r2 = rf(ctx, fromBlock, toBlock) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRollupInfoByBlockRangePreviousRollupGenesis' +type EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call struct { + *mock.Call +} + +// GetRollupInfoByBlockRangePreviousRollupGenesis is a helper method to define mock.On call +// - ctx context.Context +// - fromBlock uint64 +// - toBlock *uint64 +func (_e *EthermanPreRollup_Expecter) GetRollupInfoByBlockRangePreviousRollupGenesis(ctx interface{}, fromBlock interface{}, toBlock interface{}) *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + return &EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call{Call: _e.mock.On("GetRollupInfoByBlockRangePreviousRollupGenesis", ctx, fromBlock, toBlock)} +} + +func (_c *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) Run(run func(ctx context.Context, fromBlock uint64, toBlock *uint64)) *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(*uint64)) + }) + return _c +} + +func (_c *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) Return(_a0 []etherman.Block, _a1 map[common.Hash][]etherman.Order, _a2 error) *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call) RunAndReturn(run func(context.Context, uint64, *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error)) *EthermanPreRollup_GetRollupInfoByBlockRangePreviousRollupGenesis_Call { + _c.Call.Return(run) + return _c +} + +// NewEthermanPreRollup creates a new instance of EthermanPreRollup. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEthermanPreRollup(t interface { + mock.TestingT + Cleanup(func()) +}) *EthermanPreRollup { + mock := &EthermanPreRollup{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index a193376caa..5b575c3748 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -33,6 +33,7 @@ const ( // SequentialMode is the value for L1SynchronizationMode to run in sequential mode SequentialMode = "sequential" maxBatchNumber = ^uint64(0) + maxBlockNumber = ^uint64(0) timeOfLiveBatchOnCache = 5 * time.Minute autoDiscoverLxLyBlockNumber = uint64(0) ) @@ -633,40 +634,36 @@ func (s *ClientSynchronizer) RequestAndProcessRollupGenesisBlock(dbTx pgx.Tx, la log.Error("error getting rollupInfoByBlockRange after set the genesis: ", err) return err } - // Check that the response is the expected. It should be 1 block with 2 orders + // Check that the response is the expected. It should be 1 block with ForkID event + log.Debugf("SanityCheck for genesis block (%d) events: %+v", lastEthBlockSynced.BlockNumber, order) err = sanityCheckForGenesisBlockRollupInfo(blocks, order) if err != nil { return err } - forkId := s.state.GetForkIDByBlockNumber(blocks[0].BlockNumber) - err = s.l1EventProcessors.Process(s.ctx, actions.ForkIdType(forkId), etherman.Order{Name: etherman.ForkIDsOrder, Pos: 0}, &blocks[0], dbTx) + log.Infof("Processing genesis block %d orders: %+v", lastEthBlockSynced.BlockNumber, order) + err = s.internalProcessBlock(maxBlockNumber, blocks[0], order[blocks[0].BlockHash], false, dbTx) if err != nil { - log.Error("error storing genesis forkID: ", err) - return err - } - if len(blocks[0].SequencedBatches) != 0 { - batchSequence := l1event_orders.GetSequenceFromL1EventOrder(etherman.InitialSequenceBatchesOrder, &blocks[0], 0) - forkId = s.state.GetForkIDByBatchNumber(batchSequence.FromBatchNumber) - err = s.l1EventProcessors.Process(s.ctx, actions.ForkIdType(forkId), etherman.Order{Name: etherman.InitialSequenceBatchesOrder, Pos: 0}, &blocks[0], dbTx) - if err != nil { - log.Error("error storing initial tx (batch 1): ", err) - return err - } + log.Errorf("error processinge events on genesis block %d: err:%w", lastEthBlockSynced.BlockNumber, err) } + return nil } func sanityCheckForGenesisBlockRollupInfo(blocks []etherman.Block, order map[common.Hash][]etherman.Order) error { if len(blocks) != 1 || len(order) < 1 || len(order[blocks[0].BlockHash]) < 1 { - log.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected 1 block with 2 orders") - return fmt.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected 1 block with 2 orders") + log.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected 1 block with minimum 2 orders") + return fmt.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected 1 block with minimum 2 orders") } - if order[blocks[0].BlockHash][0].Name != etherman.ForkIDsOrder { - log.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected ForkIDsOrder, got %s", order[blocks[0].BlockHash][0].Name) - return fmt.Errorf("error getting rollupInfoByBlockRange after set the genesis. Expected ForkIDsOrder") + // The genesis block implies 1 ForkID event + for _, value := range order[blocks[0].BlockHash] { + if value.Name == etherman.ForkIDsOrder { + return nil + } } - - return nil + err := fmt.Errorf("events on genesis block (%d) need a ForkIDsOrder event but this block got %+v", + blocks[0].BlockNumber, order[blocks[0].BlockHash]) + log.Error(err.Error()) + return err } // This function syncs the node from a specific block to the latest @@ -813,67 +810,20 @@ func (s *ClientSynchronizer) ProcessBlockRange(blocks []etherman.Block, order ma log.Errorf("error creating db transaction to store block. BlockNumber: %d, error: %v", blocks[i].BlockNumber, err) return err } - b := state.Block{ - BlockNumber: blocks[i].BlockNumber, - BlockHash: blocks[i].BlockHash, - ParentHash: blocks[i].ParentHash, - ReceivedAt: blocks[i].ReceivedAt, - } - if blocks[i].BlockNumber <= finalizedBlockNumber { - b.Checked = true - } - // Add block information - err = s.state.AddBlock(s.ctx, &b, dbTx) + err = s.internalProcessBlock(finalizedBlockNumber, blocks[i], order[blocks[i].BlockHash], true, dbTx) if err != nil { + log.Error("rollingback BlockNumber: %d, because error internalProcessBlock: ", blocks[i].BlockNumber, err) // If any goes wrong we ensure that the state is rollbacked - log.Errorf("error storing block. BlockNumber: %d, error: %v", blocks[i].BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blocks[i].BlockNumber, rollbackErr.Error(), err) - return rollbackErr + if rollbackErr != nil && !errors.Is(rollbackErr, pgx.ErrTxClosed) { + log.Warnf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blocks[i].BlockNumber, rollbackErr.Error(), err) + return fmt.Errorf("error rollback BlockNumber: %d: err:%w original error:%w", blocks[i].BlockNumber, rollbackErr, err) } return err } - for _, element := range order[blocks[i].BlockHash] { - batchSequence := l1event_orders.GetSequenceFromL1EventOrder(element.Name, &blocks[i], element.Pos) - var forkId uint64 - if batchSequence != nil { - forkId = s.state.GetForkIDByBatchNumber(batchSequence.FromBatchNumber) - log.Debug("EventOrder: ", element.Name, ". Batch Sequence: ", batchSequence, "forkId: ", forkId) - } else { - forkId = s.state.GetForkIDByBlockNumber(blocks[i].BlockNumber) - log.Debug("EventOrder: ", element.Name, ". BlockNumber: ", blocks[i].BlockNumber, ". forkId: ", forkId) - } - forkIdTyped := actions.ForkIdType(forkId) - // Process event received from l1 - err := s.l1EventProcessors.Process(s.ctx, forkIdTyped, element, &blocks[i], dbTx) - if err != nil { - log.Error("error: ", err) - // If any goes wrong we ensure that the state is rollbacked - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil && !errors.Is(rollbackErr, pgx.ErrTxClosed) { - log.Warnf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blocks[i].BlockNumber, rollbackErr.Error(), err) - return rollbackErr - } - return err - } - } - log.Debug("Checking FlushID to commit L1 data to db") - err = s.checkFlushID(dbTx) - if err != nil { - // If any goes wrong we ensure that the state is rollbacked - log.Errorf("error checking flushID. Error: %v", err) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Errorf("error rolling back state. RollbackErr: %s, Error : %v", rollbackErr.Error(), err) - return rollbackErr - } - return err - } err = dbTx.Commit(s.ctx) if err != nil { - // If any goes wrong we ensure that the state is rollbacked log.Errorf("error committing state to store block. BlockNumber: %d, err: %v", blocks[i].BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { @@ -886,6 +836,57 @@ func (s *ClientSynchronizer) ProcessBlockRange(blocks []etherman.Block, order ma return nil } +// internalProcessBlock process one iteration of events and stores the information in the db +func (s *ClientSynchronizer) internalProcessBlock(finalizedBlockNumber uint64, blocks etherman.Block, order []etherman.Order, addBlock bool, dbTx pgx.Tx) error { + var err error + // New info has to be included into the db using the state + if addBlock { + b := state.Block{ + BlockNumber: blocks.BlockNumber, + BlockHash: blocks.BlockHash, + ParentHash: blocks.ParentHash, + ReceivedAt: blocks.ReceivedAt, + } + if blocks.BlockNumber <= finalizedBlockNumber { + b.Checked = true + } + // Add block information + log.Debugf("Storing block. Block: %s", b.String()) + err = s.state.AddBlock(s.ctx, &b, dbTx) + if err != nil { + log.Errorf("error storing block. BlockNumber: %d, error: %v", blocks.BlockNumber, err) + return err + } + } + + for _, element := range order { + batchSequence := l1event_orders.GetSequenceFromL1EventOrder(element.Name, &blocks, element.Pos) + var forkId uint64 + if batchSequence != nil { + forkId = s.state.GetForkIDByBatchNumber(batchSequence.FromBatchNumber) + log.Debug("EventOrder: ", element.Name, ". Batch Sequence: ", batchSequence, "forkId: ", forkId) + } else { + forkId = s.state.GetForkIDByBlockNumber(blocks.BlockNumber) + log.Debug("EventOrder: ", element.Name, ". BlockNumber: ", blocks.BlockNumber, "forkId: ", forkId) + } + forkIdTyped := actions.ForkIdType(forkId) + // Process event received from l1 + err := s.l1EventProcessors.Process(s.ctx, forkIdTyped, element, &blocks, dbTx) + if err != nil { + log.Error("1EventProcessors.Process error: ", err) + return err + } + } + log.Debug("Checking FlushID to commit L1 data to db") + err = s.checkFlushID(dbTx) + if err != nil { + log.Errorf("error checking flushID. Error: %v", err) + return err + } + + return nil +} + func (s *ClientSynchronizer) syncTrustedState(latestSyncedBatch uint64) error { if s.syncTrustedStateExecutor == nil { return nil From 09dd64a1aab2d3ab9130620bda1f78f38c24910f Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:46:19 +0200 Subject: [PATCH 5/7] add new param to genesis to set deployed RollupManager block --- config/cardonagenesis.go | 1 + config/mainnetgenesis.go | 1 + config/network.go | 9 ++-- config/network_test.go | 6 ++- etherman/etherman.go | 17 ++---- state/genesis.go | 7 +++ synchronizer/synchronizer.go | 20 +++---- synchronizer/synchronizer_test.go | 90 +++++++++++++++---------------- 8 files changed, 78 insertions(+), 73 deletions(-) diff --git a/config/cardonagenesis.go b/config/cardonagenesis.go index 0a77b9ca30..235bf0fc17 100644 --- a/config/cardonagenesis.go +++ b/config/cardonagenesis.go @@ -12,6 +12,7 @@ const CardonaNetworkConfigJSON = ` "chainId": 11155111 }, "genesisBlockNumber": 4789190, + "rollupManagerCreationBlockNumber": 4789190, "root": "0x91dfcdeb628dfdc51f3a2ee38cb17c78581e4e7ff91bcc2e327d24a9dfa46982", "genesis": [ { diff --git a/config/mainnetgenesis.go b/config/mainnetgenesis.go index 4c1800376f..71dd6e3c13 100644 --- a/config/mainnetgenesis.go +++ b/config/mainnetgenesis.go @@ -12,6 +12,7 @@ const MainnetNetworkConfigJSON = ` }, "root": "0x3f86b09b43e3e49a41fc20a07579b79eba044253367817d5c241d23c0e2bc5c9", "genesisBlockNumber": 16896721, + "rollupManagerCreationBlockNumber": 16896721, "genesis": [ { "contractName": "PolygonZkEVMDeployer", diff --git a/config/network.go b/config/network.go index 20094ee8ab..5aefec48d0 100644 --- a/config/network.go +++ b/config/network.go @@ -36,6 +36,8 @@ type GenesisFromJSON struct { Root string `json:"root"` // L1: block number of the genesis block GenesisBlockNum uint64 `json:"genesisBlockNumber"` + // rollupManagerCreationBlockNumber is the block number where the RollupManager smc was deployed on L1 (0 auto-discover) + RollupManagerCreationBlockNumber uint64 `json:"rollupManagerCreationBlockNumber"` // L2: List of states contracts used to populate merkle tree at initial state Genesis []genesisAccountFromJSON `json:"genesis"` // L1: configuration of the network @@ -122,9 +124,10 @@ func LoadGenesisFromJSONString(jsonStr string) (NetworkConfig, error) { cfg.L1Config = cfgJSON.L1Config cfg.Genesis = state.Genesis{ - BlockNumber: cfgJSON.GenesisBlockNum, - Root: common.HexToHash(cfgJSON.Root), - Actions: []*state.GenesisAction{}, + BlockNumber: cfgJSON.GenesisBlockNum, + Root: common.HexToHash(cfgJSON.Root), + RollupManagerBlockNumber: cfgJSON.RollupManagerCreationBlockNumber, + Actions: []*state.GenesisAction{}, } for _, account := range cfgJSON.Genesis { diff --git a/config/network_test.go b/config/network_test.go index 1d126ce986..a89bb3f759 100644 --- a/config/network_test.go +++ b/config/network_test.go @@ -38,6 +38,7 @@ func TestLoadCustomNetworkConfig(t *testing.T) { inputConfigStr: `{ "root": "0xBEEF", "genesisBlockNumber": 69, + "rollupManagerCreationBlockNumber": 68, "l1Config" : { "chainId": 420, "polygonZkEVMAddress": "0xc949254d682d8c9ad5682521675b8f43b102aec4", @@ -89,8 +90,9 @@ func TestLoadCustomNetworkConfig(t *testing.T) { GlobalExitRootManagerAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), }, Genesis: state.Genesis{ - Root: common.HexToHash("0xBEEF"), - BlockNumber: 69, + Root: common.HexToHash("0xBEEF"), + BlockNumber: 69, + RollupManagerBlockNumber: 68, Actions: []*state.GenesisAction{ { Address: "0xc949254d682d8c9ad5682521675b8f43b102aec4", diff --git a/etherman/etherman.go b/etherman/etherman.go index 377d8b3519..4b9149fb9f 100644 --- a/etherman/etherman.go +++ b/etherman/etherman.go @@ -41,11 +41,6 @@ import ( "golang.org/x/crypto/sha3" ) -const ( - // ETrogUpgradeVersion is the version of the LxLy upgrade - ETrogUpgradeVersion = 2 -) - var ( // Events RollupManager setBatchFeeSignatureHash = crypto.Keccak256Hash([]byte("SetBatchFee(uint256)")) @@ -346,20 +341,18 @@ func (etherMan *Client) VerifyGenBlockNumber(ctx context.Context, genBlockNumber // GetL1BlockUpgradeLxLy It returns the block genesis for LxLy before genesisBlock or error func (etherMan *Client) GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) { - it, err := etherMan.RollupManager.FilterInitialized(&bind.FilterOpts{ + + it, err := etherMan.GlobalExitRootManager.FilterUpdateL1InfoTree(&bind.FilterOpts{ Start: 1, End: &genesisBlock, Context: ctx, - }) + }, nil, nil) if err != nil { return uint64(0), err } for it.Next() { - log.Debugf("BlockNumber: %d Topics:Initialized(%d)", it.Event.Raw.BlockNumber, it.Event.Version) - if it.Event.Version == ETrogUpgradeVersion { // 2 is ETROG (LxLy upgrade) - log.Infof("LxLy upgrade found at blockNumber: %d", it.Event.Raw.BlockNumber) - return it.Event.Raw.BlockNumber, nil - } + log.Debugf("BlockNumber: %d Topics:L1InfoTree", it.Event.Raw.BlockNumber) + return it.Event.Raw.BlockNumber, nil } return uint64(0), ErrNotFound } diff --git a/state/genesis.go b/state/genesis.go index 50c4b5a950..726c0739e9 100644 --- a/state/genesis.go +++ b/state/genesis.go @@ -17,12 +17,19 @@ import ( "github.com/jackc/pgx/v4" ) +const ( + // AutoDiscoverRollupManagerBlockNumber is the value to auto-discover the RollupManager creation block number + AutoDiscoverRollupManagerBlockNumber = uint64(0) +) + // Genesis contains the information to populate state on creation type Genesis struct { // BlockNumber is the block number where the polygonZKEVM smc was deployed on L1 BlockNumber uint64 // Root hash of the genesis block Root common.Hash + // RollupManagerBlockNumber is the block number where the RollupManager smc was deployed on L1 if if set to AutoDiscoverRollupManagerBlockNumber(0) then is auto-discovered + RollupManagerBlockNumber uint64 // Actions is the data to populate into the state trie Actions []*GenesisAction } diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index 5b575c3748..074912e419 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -31,11 +31,10 @@ const ( // ParallelMode is the value for L1SynchronizationMode to run in parallel mode ParallelMode = "parallel" // SequentialMode is the value for L1SynchronizationMode to run in sequential mode - SequentialMode = "sequential" - maxBatchNumber = ^uint64(0) - maxBlockNumber = ^uint64(0) - timeOfLiveBatchOnCache = 5 * time.Minute - autoDiscoverLxLyBlockNumber = uint64(0) + SequentialMode = "sequential" + maxBatchNumber = ^uint64(0) + maxBlockNumber = ^uint64(0) + timeOfLiveBatchOnCache = 5 * time.Minute ) // Synchronizer connects L1 and L2 @@ -298,20 +297,21 @@ func (s *ClientSynchronizer) isGenesisProcessed(ctx context.Context, dbTx pgx.Tx // bool -> need to process blocks // uint64 -> first block to synchronize // error -> error -// 1. First try to get last block on DB, if there are could be fully synced or pending blocks -// 2. If DB is empty the LxLy upgrade block as starting point +// 1. Check last synced block on DB, if there are any could be fully synced (>=genesis) or syncing pre-genesis events ( Date: Tue, 3 Sep 2024 16:00:31 +0200 Subject: [PATCH 6/7] update documentation --- .../custom_network-config-doc.html | 2 +- docs/config-file/custom_network-config-doc.md | 48 +++++++++++-------- .../custom_network-config-schema.json | 4 ++ docs/config-file/node-config-doc.html | 2 +- docs/config-file/node-config-doc.md | 43 +++++++++++------ docs/config-file/node-config-schema.json | 5 ++ 6 files changed, 67 insertions(+), 37 deletions(-) diff --git a/docs/config-file/custom_network-config-doc.html b/docs/config-file/custom_network-config-doc.html index 03d7138dd2..fb09620f20 100644 --- a/docs/config-file/custom_network-config-doc.html +++ b/docs/config-file/custom_network-config-doc.html @@ -1 +1 @@ - Schema Docs

GenesisFromJSON is the config file for network_custom

Type: string

L1: root hash of the genesis block


Type: integer

L1: block number of the genesis block


Type: array of object

L2: List of states contracts used to populate merkle tree at initial state

Each item of this array must be:


L1: configuration of the network
Type: integer

Chain ID of the L1 network


Type: array of integer

ZkEVMAddr Address of the L1 contract polygonZkEVMAddress

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

RollupManagerAddr Address of the L1 contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

PolAddr Address of the L1 Pol token Contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


\ No newline at end of file + Schema Docs

GenesisFromJSON is the config file for network_custom

Type: string

L1: root hash of the genesis block


Type: integer

L1: block number of the genesis block


Type: integer

rollupManagerCreationBlockNumber is the block number where the RollupManager smc was deployed on L1 (0 auto-discover)


Type: array of object

L2: List of states contracts used to populate merkle tree at initial state

Each item of this array must be:


L1: configuration of the network
Type: integer

Chain ID of the L1 network


Type: array of integer

ZkEVMAddr Address of the L1 contract polygonZkEVMAddress

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

RollupManagerAddr Address of the L1 contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

PolAddr Address of the L1 Pol token Contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


\ No newline at end of file diff --git a/docs/config-file/custom_network-config-doc.md b/docs/config-file/custom_network-config-doc.md index 2a29dde7f6..90a216ff6f 100644 --- a/docs/config-file/custom_network-config-doc.md +++ b/docs/config-file/custom_network-config-doc.md @@ -3,12 +3,13 @@ **Type:** : `object` **Description:** GenesisFromJSON is the config file for network_custom -| Property | Pattern | Type | Deprecated | Definition | Title/Description | -| -------------------------------------------- | ------- | --------------- | ---------- | ---------- | --------------------------------------------------------------------------- | -| - [root](#root ) | No | string | No | - | L1: root hash of the genesis block | -| - [genesisBlockNumber](#genesisBlockNumber ) | No | integer | No | - | L1: block number of the genesis block | -| - [genesis](#genesis ) | No | array of object | No | - | L2: List of states contracts used to populate merkle tree at initial state | -| - [L1Config](#L1Config ) | No | object | No | - | L1: configuration of the network | +| Property | Pattern | Type | Deprecated | Definition | Title/Description | +| ------------------------------------------------------------------------ | ------- | --------------- | ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------- | +| - [root](#root ) | No | string | No | - | L1: root hash of the genesis block | +| - [genesisBlockNumber](#genesisBlockNumber ) | No | integer | No | - | L1: block number of the genesis block | +| - [rollupManagerCreationBlockNumber](#rollupManagerCreationBlockNumber ) | No | integer | No | - | rollupManagerCreationBlockNumber is the block number where the RollupManager smc was deployed on L1 (0 auto-discover) | +| - [genesis](#genesis ) | No | array of object | No | - | L2: List of states contracts used to populate merkle tree at initial state | +| - [L1Config](#L1Config ) | No | object | No | - | L1: configuration of the network | ## 1. `root` @@ -20,7 +21,12 @@ **Type:** : `integer` **Description:** L1: block number of the genesis block -## 3. `genesis` +## 3. `rollupManagerCreationBlockNumber` + +**Type:** : `integer` +**Description:** rollupManagerCreationBlockNumber is the block number where the RollupManager smc was deployed on L1 (0 auto-discover) + +## 4. `genesis` **Type:** : `array of object` **Description:** L2: List of states contracts used to populate merkle tree at initial state @@ -37,7 +43,7 @@ | ------------------------------- | ----------- | | [genesis items](#genesis_items) | - | -### 3.1. [genesis.genesis items] +### 4.1. [genesis.genesis items] **Type:** : `object` @@ -50,23 +56,23 @@ | - [storage](#genesis_items_storage ) | No | object | No | - | - | | - [contractName](#genesis_items_contractName ) | No | string | No | - | - | -#### 3.1.1. `genesis.genesis items.balance` +#### 4.1.1. `genesis.genesis items.balance` **Type:** : `string` -#### 3.1.2. `genesis.genesis items.nonce` +#### 4.1.2. `genesis.genesis items.nonce` **Type:** : `string` -#### 3.1.3. `genesis.genesis items.address` +#### 4.1.3. `genesis.genesis items.address` **Type:** : `string` -#### 3.1.4. `genesis.genesis items.bytecode` +#### 4.1.4. `genesis.genesis items.bytecode` **Type:** : `string` -#### 3.1.5. `[genesis.genesis items.storage]` +#### 4.1.5. `[genesis.genesis items.storage]` **Type:** : `object` @@ -74,15 +80,15 @@ | -------------------------------------------------- | ------- | ------ | ---------- | ---------- | ----------------- | | - [](#genesis_items_storage_additionalProperties ) | No | string | No | - | - | -##### 3.1.5.1. `genesis.genesis items.storage.additionalProperties` +##### 4.1.5.1. `genesis.genesis items.storage.additionalProperties` **Type:** : `string` -#### 3.1.6. `genesis.genesis items.contractName` +#### 4.1.6. `genesis.genesis items.contractName` **Type:** : `string` -## 4. `[L1Config]` +## 5. `[L1Config]` **Type:** : `object` **Description:** L1: configuration of the network @@ -95,27 +101,27 @@ | - [polTokenAddress](#L1Config_polTokenAddress ) | No | array of integer | No | - | PolAddr Address of the L1 Pol token Contract | | - [polygonZkEVMGlobalExitRootAddress](#L1Config_polygonZkEVMGlobalExitRootAddress ) | No | array of integer | No | - | GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract | -### 4.1. `L1Config.chainId` +### 5.1. `L1Config.chainId` **Type:** : `integer` **Description:** Chain ID of the L1 network -### 4.2. `L1Config.polygonZkEVMAddress` +### 5.2. `L1Config.polygonZkEVMAddress` **Type:** : `array of integer` **Description:** ZkEVMAddr Address of the L1 contract polygonZkEVMAddress -### 4.3. `L1Config.polygonRollupManagerAddress` +### 5.3. `L1Config.polygonRollupManagerAddress` **Type:** : `array of integer` **Description:** RollupManagerAddr Address of the L1 contract -### 4.4. `L1Config.polTokenAddress` +### 5.4. `L1Config.polTokenAddress` **Type:** : `array of integer` **Description:** PolAddr Address of the L1 Pol token Contract -### 4.5. `L1Config.polygonZkEVMGlobalExitRootAddress` +### 5.5. `L1Config.polygonZkEVMGlobalExitRootAddress` **Type:** : `array of integer` **Description:** GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract diff --git a/docs/config-file/custom_network-config-schema.json b/docs/config-file/custom_network-config-schema.json index 835bee3cab..19d72a6d9a 100644 --- a/docs/config-file/custom_network-config-schema.json +++ b/docs/config-file/custom_network-config-schema.json @@ -10,6 +10,10 @@ "type": "integer", "description": "L1: block number of the genesis block" }, + "rollupManagerCreationBlockNumber": { + "type": "integer", + "description": "rollupManagerCreationBlockNumber is the block number where the RollupManager smc was deployed on L1 (0 auto-discover)" + }, "genesis": { "items": { "properties": { diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html index 0c5400fb2a..5fefa2acd6 100644 --- a/docs/config-file/node-config-doc.html +++ b/docs/config-file/node-config-doc.html @@ -78,7 +78,7 @@
"300ms"
 

Default: 0Type: integer

ChainID is the L2 ChainID provided by the Network Config


Default: 0Type: integer

ForkID is the L2 ForkID provided by the Network Config


Default: ""Type: string

SenderAddress defines which private key the eth tx manager needs to use
to sign the L1 txs


Default: "2m0s"Type: string

CleanupLockedProofsInterval is the interval of time to clean up locked proofs.


Examples:

"1m"
 
"300ms"
-

Default: "10m"Type: string

GeneratingProofCleanupThreshold represents the time interval after
which a proof in generating state is considered to be stuck and
allowed to be cleared.


Default: 0Type: integer

GasOffset is the amount of gas to be added to the gas estimation in order
to provide an amount that is higher than the estimated one. This is used
to avoid the TX getting reverted in case something has changed in the network
state after the estimation which can cause the TX to require more gas to be
executed.

ex:
gas estimation: 1000
gas offset: 100
final gas: 1100


Default: 0Type: integer

UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog


Default: 2Type: integer

BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch


Configuration of the genesis of the network. This is used to known the initial state of the network

L1: Configuration related to L1
Default: 0Type: integer

Chain ID of the L1 network


Type: array of integer

ZkEVMAddr Address of the L1 contract polygonZkEVMAddress

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

RollupManagerAddr Address of the L1 contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

PolAddr Address of the L1 Pol token Contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


L1: Genesis of the rollup, first block number and root
Default: 0Type: integer

BlockNumber is the block number where the polygonZKEVM smc was deployed on L1


Type: array of integer

Root hash of the genesis block

Must contain a minimum of 32 items

Must contain a maximum of 32 items

Each item of this array must be:


Type: array of object

Actions is the data to populate into the state trie

Each item of this array must be:


Configuration of the gas price suggester service
Default: "follower"Type: string

Default: 2000000000Type: integer

DefaultGasPriceWei is used to set the gas price to be used by the default gas pricer or as minimim gas price by the follower gas pricer.


Default: 0Type: integer

MaxGasPriceWei is used to limit the gas price returned by the follower gas pricer to a maximum value. It is ignored if 0.


Default: 0Type: integer

Default: 0Type: integer

Default: "10s"Type: string

Examples:

"1m"
+

Default: "10m"Type: string

GeneratingProofCleanupThreshold represents the time interval after
which a proof in generating state is considered to be stuck and
allowed to be cleared.


Default: 0Type: integer

GasOffset is the amount of gas to be added to the gas estimation in order
to provide an amount that is higher than the estimated one. This is used
to avoid the TX getting reverted in case something has changed in the network
state after the estimation which can cause the TX to require more gas to be
executed.

ex:
gas estimation: 1000
gas offset: 100
final gas: 1100


Default: 0Type: integer

UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog


Default: 2Type: integer

BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch


Configuration of the genesis of the network. This is used to known the initial state of the network

L1: Configuration related to L1
Default: 0Type: integer

Chain ID of the L1 network


Type: array of integer

ZkEVMAddr Address of the L1 contract polygonZkEVMAddress

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

RollupManagerAddr Address of the L1 contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

PolAddr Address of the L1 Pol token Contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


Type: array of integer

GlobalExitRootManagerAddr Address of the L1 GlobalExitRootManager contract

Must contain a minimum of 20 items

Must contain a maximum of 20 items

Each item of this array must be:


L1: Genesis of the rollup, first block number and root
Default: 0Type: integer

BlockNumber is the block number where the polygonZKEVM smc was deployed on L1


Type: array of integer

Root hash of the genesis block

Must contain a minimum of 32 items

Must contain a maximum of 32 items

Each item of this array must be:


Default: 0Type: integer

RollupManagerBlockNumber is the block number where the RollupManager smc was deployed on L1 if if set to AutoDiscoverRollupManagerBlockNumber(0) then is auto-discovered


Type: array of object

Actions is the data to populate into the state trie

Each item of this array must be:


Configuration of the gas price suggester service
Default: "follower"Type: string

Default: 2000000000Type: integer

DefaultGasPriceWei is used to set the gas price to be used by the default gas pricer or as minimim gas price by the follower gas pricer.


Default: 0Type: integer

MaxGasPriceWei is used to limit the gas price returned by the follower gas pricer to a maximum value. It is ignored if 0.


Default: 0Type: integer

Default: 0Type: integer

Default: "10s"Type: string

Examples:

"1m"
 
"300ms"
 

Default: "1h0m0s"Type: string

Examples:

"1m"
 
"300ms"
diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md
index dc70d93791..965f3049b9 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -3306,11 +3306,12 @@ chainId=0
 **Type:** : `object`
 **Description:** L1: Genesis of the rollup, first block number and root
 
-| Property                                             | Pattern | Type             | Deprecated | Definition | Title/Description                                                             |
-| ---------------------------------------------------- | ------- | ---------------- | ---------- | ---------- | ----------------------------------------------------------------------------- |
-| - [BlockNumber](#NetworkConfig_Genesis_BlockNumber ) | No      | integer          | No         | -          | BlockNumber is the block number where the polygonZKEVM smc was deployed on L1 |
-| - [Root](#NetworkConfig_Genesis_Root )               | No      | array of integer | No         | -          | Root hash of the genesis block                                                |
-| - [Actions](#NetworkConfig_Genesis_Actions )         | No      | array of object  | No         | -          | Actions is the data to populate into the state trie                           |
+| Property                                                                       | Pattern | Type             | Deprecated | Definition | Title/Description                                                                                                                                                        |
+| ------------------------------------------------------------------------------ | ------- | ---------------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| - [BlockNumber](#NetworkConfig_Genesis_BlockNumber )                           | No      | integer          | No         | -          | BlockNumber is the block number where the polygonZKEVM smc was deployed on L1                                                                                            |
+| - [Root](#NetworkConfig_Genesis_Root )                                         | No      | array of integer | No         | -          | Root hash of the genesis block                                                                                                                                           |
+| - [RollupManagerBlockNumber](#NetworkConfig_Genesis_RollupManagerBlockNumber ) | No      | integer          | No         | -          | RollupManagerBlockNumber is the block number where the RollupManager smc was deployed on L1 if if set to AutoDiscoverRollupManagerBlockNumber(0) then is auto-discovered |
+| - [Actions](#NetworkConfig_Genesis_Actions )                                   | No      | array of object  | No         | -          | Actions is the data to populate into the state trie                                                                                                                      |
 
 #### 13.2.1. `NetworkConfig.Genesis.BlockNumber`
 
@@ -3331,7 +3332,21 @@ BlockNumber=0
 **Type:** : `array of integer`
 **Description:** Root hash of the genesis block
 
-#### 13.2.3. `NetworkConfig.Genesis.Actions`
+#### 13.2.3. `NetworkConfig.Genesis.RollupManagerBlockNumber`
+
+**Type:** : `integer`
+
+**Default:** `0`
+
+**Description:** RollupManagerBlockNumber is the block number where the RollupManager smc was deployed on L1 if if set to AutoDiscoverRollupManagerBlockNumber(0) then is auto-discovered
+
+**Example setting the default value** (0):
+```
+[NetworkConfig.Genesis]
+RollupManagerBlockNumber=0
+```
+
+#### 13.2.4. `NetworkConfig.Genesis.Actions`
 
 **Type:** : `array of object`
 **Description:** Actions is the data to populate into the state trie
@@ -3348,7 +3363,7 @@ BlockNumber=0
 | ----------------------------------------------------- | ------------------------------------------------------------------------- |
 | [Actions items](#NetworkConfig_Genesis_Actions_items) | GenesisAction represents one of the values set on the SMT during genesis. |
 
-##### 13.2.3.1. [NetworkConfig.Genesis.Actions.Actions items]
+##### 13.2.4.1. [NetworkConfig.Genesis.Actions.Actions items]
 
 **Type:** : `object`
 **Description:** GenesisAction represents one of the values set on the SMT during genesis.
@@ -3363,31 +3378,31 @@ BlockNumber=0
 | - [value](#NetworkConfig_Genesis_Actions_items_value )                     | No      | string  | No         | -          | -                 |
 | - [root](#NetworkConfig_Genesis_Actions_items_root )                       | No      | string  | No         | -          | -                 |
 
-##### 13.2.3.1.1. `NetworkConfig.Genesis.Actions.Actions items.address`
+##### 13.2.4.1.1. `NetworkConfig.Genesis.Actions.Actions items.address`
 
 **Type:** : `string`
 
-##### 13.2.3.1.2. `NetworkConfig.Genesis.Actions.Actions items.type`
+##### 13.2.4.1.2. `NetworkConfig.Genesis.Actions.Actions items.type`
 
 **Type:** : `integer`
 
-##### 13.2.3.1.3. `NetworkConfig.Genesis.Actions.Actions items.storagePosition`
+##### 13.2.4.1.3. `NetworkConfig.Genesis.Actions.Actions items.storagePosition`
 
 **Type:** : `string`
 
-##### 13.2.3.1.4. `NetworkConfig.Genesis.Actions.Actions items.bytecode`
+##### 13.2.4.1.4. `NetworkConfig.Genesis.Actions.Actions items.bytecode`
 
 **Type:** : `string`
 
-##### 13.2.3.1.5. `NetworkConfig.Genesis.Actions.Actions items.key`
+##### 13.2.4.1.5. `NetworkConfig.Genesis.Actions.Actions items.key`
 
 **Type:** : `string`
 
-##### 13.2.3.1.6. `NetworkConfig.Genesis.Actions.Actions items.value`
+##### 13.2.4.1.6. `NetworkConfig.Genesis.Actions.Actions items.value`
 
 **Type:** : `string`
 
-##### 13.2.3.1.7. `NetworkConfig.Genesis.Actions.Actions items.root`
+##### 13.2.4.1.7. `NetworkConfig.Genesis.Actions.Actions items.root`
 
 **Type:** : `string`
 
diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json
index 5b1b218cf5..9dd30962d2 100644
--- a/docs/config-file/node-config-schema.json
+++ b/docs/config-file/node-config-schema.json
@@ -1311,6 +1311,11 @@
 							"minItems": 32,
 							"description": "Root hash of the genesis block"
 						},
+						"RollupManagerBlockNumber": {
+							"type": "integer",
+							"description": "RollupManagerBlockNumber is the block number where the RollupManager smc was deployed on L1 if if set to AutoDiscoverRollupManagerBlockNumber(0) then is auto-discovered",
+							"default": 0
+						},
 						"Actions": {
 							"items": {
 								"properties": {

From bc19aeccaeaa2afa049e649d2e3a9bcbaf7f51c8 Mon Sep 17 00:00:00 2001
From: joanestebanr <129153821+joanestebanr@users.noreply.github.com>
Date: Tue, 3 Sep 2024 17:57:30 +0200
Subject: [PATCH 7/7] fix lint

---
 etherman/etherman.go                             | 1 -
 synchronizer/l1_parallel_sync/l1_data_message.go | 4 ++--
 synchronizer/synchronizer_test.go                | 1 -
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/etherman/etherman.go b/etherman/etherman.go
index 4b9149fb9f..18f1206505 100644
--- a/etherman/etherman.go
+++ b/etherman/etherman.go
@@ -341,7 +341,6 @@ func (etherMan *Client) VerifyGenBlockNumber(ctx context.Context, genBlockNumber
 
 // GetL1BlockUpgradeLxLy It returns the block genesis for LxLy before genesisBlock or error
 func (etherMan *Client) GetL1BlockUpgradeLxLy(ctx context.Context, genesisBlock uint64) (uint64, error) {
-
 	it, err := etherMan.GlobalExitRootManager.FilterUpdateL1InfoTree(&bind.FilterOpts{
 		Start:   1,
 		End:     &genesisBlock,
diff --git a/synchronizer/l1_parallel_sync/l1_data_message.go b/synchronizer/l1_parallel_sync/l1_data_message.go
index b84b4299cd..83fdb958d7 100644
--- a/synchronizer/l1_parallel_sync/l1_data_message.go
+++ b/synchronizer/l1_parallel_sync/l1_data_message.go
@@ -65,12 +65,12 @@ func newL1SyncMessageControlWProducerIsFullySynced(lastBlock uint64) *L1SyncMess
 }
 
 func newL1SyncMessageData(result *rollupInfoByBlockRangeResult) *L1SyncMessage {
-	if result == nil {
+	if result == nil { //nolint:all
 		log.Fatal("newL1PackageDataFromResult: result is nil, the idea of this func is create packages with data")
 	}
 	return &L1SyncMessage{
 		dataIsValid: true,
-		data:        *result,
+		data:        *result, //nolint:all
 		ctrlIsValid: false,
 	}
 }
diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go
index f2f53dab0e..8337948c8f 100644
--- a/synchronizer/synchronizer_test.go
+++ b/synchronizer/synchronizer_test.go
@@ -78,7 +78,6 @@ func TestGetStartingL1BlockAutodiscover(t *testing.T) {
 		require.True(t, needProcess)
 		require.Equal(t, uint64(101), firstBlock)
 	})
-
 }
 
 // Feature #2220 and  #2239: Optimize Trusted state synchronization