Skip to content

Commit

Permalink
add new param to genesis to set deployed RollupManager block
Browse files Browse the repository at this point in the history
  • Loading branch information
joanestebanr committed Sep 3, 2024
1 parent de53232 commit 09dd64a
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 73 deletions.
1 change: 1 addition & 0 deletions config/cardonagenesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const CardonaNetworkConfigJSON = `
"chainId": 11155111
},
"genesisBlockNumber": 4789190,
"rollupManagerCreationBlockNumber": 4789190,
"root": "0x91dfcdeb628dfdc51f3a2ee38cb17c78581e4e7ff91bcc2e327d24a9dfa46982",
"genesis": [
{
Expand Down
1 change: 1 addition & 0 deletions config/mainnetgenesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const MainnetNetworkConfigJSON = `
},
"root": "0x3f86b09b43e3e49a41fc20a07579b79eba044253367817d5c241d23c0e2bc5c9",
"genesisBlockNumber": 16896721,
"rollupManagerCreationBlockNumber": 16896721,
"genesis": [
{
"contractName": "PolygonZkEVMDeployer",
Expand Down
9 changes: 6 additions & 3 deletions config/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 4 additions & 2 deletions config/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func TestLoadCustomNetworkConfig(t *testing.T) {
inputConfigStr: `{
"root": "0xBEEF",
"genesisBlockNumber": 69,
"rollupManagerCreationBlockNumber": 68,
"l1Config" : {
"chainId": 420,
"polygonZkEVMAddress": "0xc949254d682d8c9ad5682521675b8f43b102aec4",
Expand Down Expand Up @@ -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",
Expand Down
17 changes: 5 additions & 12 deletions etherman/etherman.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)"))
Expand Down Expand Up @@ -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
}
Expand Down
7 changes: 7 additions & 0 deletions state/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
20 changes: 10 additions & 10 deletions synchronizer/synchronizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 (<genesis)
// 2. If no block DB then get the LxLy upgrade block as starting point for pre-genesis or use the genesis 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 {
if upgradeLxLyBlockNumber == state.AutoDiscoverRollupManagerBlockNumber {
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)
log.Errorf("sync pre-genesis: error getting LxLy upgrade block. Maybe your provider doesnt support eth_getLogs big block range,"+
".Suggestion: inform the field rollupManagerCreationBlockNumber in genesis file to avoid auto-discover. Error: %v", err)
return false, 0, err
}
}
Expand All @@ -337,7 +337,7 @@ func (s *ClientSynchronizer) synchronizePreGenesisRollupEvents(syncChunkSize uin
// 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
rollupManagerBlockNumber := s.genesis.RollupManagerBlockNumber
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)
Expand Down
90 changes: 44 additions & 46 deletions synchronizer/synchronizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package synchronizer

import (
context "context"
"fmt"
"math"
"math/big"
"testing"
Expand Down Expand Up @@ -45,6 +46,41 @@ type mocks struct {
//EventLog *eventLogMock
}

func TestGetStartingL1BlockAutodiscover(t *testing.T) {
genesis, cfg, m := setupGenericTest(t)
ethermanForL1 := []syncinterfaces.EthermanFullInterface{m.Etherman}
syncInterface, err := NewSynchronizer(false, m.Etherman, ethermanForL1, m.State, m.Pool, m.EthTxManager, m.ZKEVMClient, m.zkEVMClientEthereumCompatible, nil, *genesis, *cfg, false)
require.NoError(t, err)
sync, ok := syncInterface.(*ClientSynchronizer)
require.True(t, ok)
ctx := context.TODO()
t.Run("getStartingL1Block autodiscover OK", func(t *testing.T) {
m.State.EXPECT().GetLastBlock(ctx, nil).Return(nil, state.ErrStateNotSynchronized).Once()
m.Etherman.EXPECT().GetL1BlockUpgradeLxLy(mock.Anything, mock.Anything).Return(uint64(100), nil).Once()
needProcess, firstBlock, err := sync.getStartingL1Block(ctx, 123, 0, nil)
require.NoError(t, err)
require.True(t, needProcess)
require.Equal(t, uint64(100), firstBlock)
})

t.Run("getStartingL1Block autodiscover Fails", func(t *testing.T) {
m.State.EXPECT().GetLastBlock(ctx, nil).Return(nil, state.ErrStateNotSynchronized).Once()
m.Etherman.EXPECT().GetL1BlockUpgradeLxLy(mock.Anything, mock.Anything).Return(uint64(0), fmt.Errorf("error")).Once()
_, _, err = sync.getStartingL1Block(ctx, 123, 0, nil)
require.Error(t, err)
})

t.Run("getStartingL1Block have already started sync", func(t *testing.T) {
m.State.EXPECT().GetLastBlock(ctx, nil).Return(&state.Block{BlockNumber: 100}, nil).Once()

needProcess, firstBlock, err := sync.getStartingL1Block(ctx, 123, 0, nil)
require.NoError(t, err)
require.True(t, needProcess)
require.Equal(t, uint64(101), firstBlock)
})

}

// Feature #2220 and #2239: Optimize Trusted state synchronization
//
// this Check partially point 2: Use previous batch stored in memory to avoid getting from database
Expand Down Expand Up @@ -180,10 +216,6 @@ func TestForcedBatchEtrog(t *testing.T) {
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(7), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock0, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Expand Down Expand Up @@ -432,37 +464,28 @@ func TestSequenceForcedBatchIncaberry(t *testing.T) {

// state preparation
ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil })

parentHash := common.HexToHash("0xb14c74e4dddf25627a745f46cae6ac98782e2783c3ccc28107c8210e60d58861")
ethHeader := &ethTypes.Header{Number: big.NewInt(1), ParentHash: parentHash}
ethBlock := ethTypes.NewBlockWithHeader(ethHeader)
lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64(), ParentHash: ethBlock.ParentHash()}
parentHash := common.HexToHash("0x111")
ethHeader0 := &ethTypes.Header{Number: big.NewInt(1), ParentHash: parentHash}
ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0)
ethHeader1 := &ethTypes.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()}

m.State.
On("GetLastBlock", mock.Anything, nil).
Return(lastBlock, nil).
Return(lastBlock0, nil).
Once()

m.State.
On("BeginStateTransaction", ctxMatchBy).
Run(func(args mock.Arguments) {
ctx := args[0].(context.Context)
ethHeader0 := &ethTypes.Header{Number: big.NewInt(1), ParentHash: parentHash}
ethBlock0 := ethTypes.NewBlockWithHeader(ethHeader0)
ethHeader1 := &ethTypes.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()}
m.State.
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(1), nil).
Maybe()

m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock0, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Return(uint64(10), nil).
Expand Down Expand Up @@ -1017,10 +1040,6 @@ func TestReorg(t *testing.T) {
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(9), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock1, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Expand Down Expand Up @@ -1333,16 +1352,10 @@ func TestLatestSyncedBlockEmpty(t *testing.T) {
On("BeginStateTransaction", ctxMatchBy).
Run(func(args mock.Arguments) {
ctx := args[0].(context.Context)

m.State.
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(9), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock1, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Return(uint64(10), nil).
Expand Down Expand Up @@ -1556,15 +1569,10 @@ func TestRegularReorg(t *testing.T) {
On("BeginStateTransaction", ctxMatchBy).
Run(func(args mock.Arguments) {
ctx := args[0].(context.Context)

m.State.
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(9), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock1, nil).
Maybe()

// After a ResetState get lastblock that must be block 0
m.State.
Expand Down Expand Up @@ -1851,11 +1859,6 @@ func TestLatestSyncedBlockEmptyWithExtraReorg(t *testing.T) {
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(9), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock2, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Return(uint64(10), nil).
Expand Down Expand Up @@ -2132,11 +2135,6 @@ func TestCallFromEmptyBlockAndReorg(t *testing.T) {
On("GetForkIDByBatchNumber", mock.Anything).
Return(uint64(9), nil).
Maybe()
m.State.
On("GetLastBlock", ctx, m.DbTx).
Return(lastBlock1, nil).
Maybe()

m.State.
On("GetLastBatchNumber", ctx, m.DbTx).
Return(uint64(10), nil).
Expand Down

0 comments on commit 09dd64a

Please sign in to comment.