Skip to content

Commit

Permalink
Feature/#3544 sync block protection (#3545)
Browse files Browse the repository at this point in the history
* SyncBlockProtection parameter

* linter

* config

* Fix unit test
  • Loading branch information
ARR552 committed Apr 9, 2024
1 parent 602aed0 commit 09f9151
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 27 deletions.
1 change: 1 addition & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ EnableHttpLog = true
SyncInterval = "1s"
SyncChunkSize = 100
TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc
SyncBlockProtection = "latest" # latest, finalized, safe
L1SynchronizationMode = "sequential"
L1SyncCheckL2BlockHash = true
L1SyncCheckL2BlockNumberhModulus = 30
Expand Down
1 change: 1 addition & 0 deletions config/environments/local/local.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ EnableL2SuggestedGasPricePolling = true
SyncInterval = "1s"
SyncChunkSize = 100
TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc
SyncBlockProtection = "latest" # latest, finalized, safe

[Sequencer]
DeletePoolTxsL1BlockConfirmations = 100
Expand Down
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

55 changes: 35 additions & 20 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,7 @@ because depending of this values is going to ask to a trusted node for trusted t
| - [SyncInterval](#Synchronizer_SyncInterval ) | No | string | No | - | Duration |
| - [SyncChunkSize](#Synchronizer_SyncChunkSize ) | No | integer | No | - | SyncChunkSize is the number of blocks to sync on each chunk |
| - [TrustedSequencerURL](#Synchronizer_TrustedSequencerURL ) | No | string | No | - | TrustedSequencerURL is the rpc url to connect and sync the trusted state |
| - [SyncBlockProtection](#Synchronizer_SyncBlockProtection ) | No | string | No | - | SyncBlockProtection specify the state to sync (lastest, finalized or safe) |
| - [L1SyncCheckL2BlockHash](#Synchronizer_L1SyncCheckL2BlockHash ) | No | boolean | No | - | L1SyncCheckL2BlockHash if is true when a batch is closed is force to check L2Block hash against trustedNode (only apply for permissionless) |
| - [L1SyncCheckL2BlockNumberhModulus](#Synchronizer_L1SyncCheckL2BlockNumberhModulus ) | No | integer | No | - | L1SyncCheckL2BlockNumberhModulus is the modulus used to choose the l2block to check<br />a modules 5, for instance, means check all l2block multiples of 5 (10,15,20,...) |
| - [L1SynchronizationMode](#Synchronizer_L1SynchronizationMode ) | No | enum (of string) | No | - | L1SynchronizationMode define how to synchronize with L1:<br />- parallel: Request data to L1 in parallel, and process sequentially. The advantage is that executor is not blocked waiting for L1 data<br />- sequential: Request data to L1 and execute |
Expand Down Expand Up @@ -1399,7 +1400,21 @@ SyncChunkSize=100
TrustedSequencerURL=""
```

### <a name="Synchronizer_L1SyncCheckL2BlockHash"></a>9.4. `Synchronizer.L1SyncCheckL2BlockHash`
### <a name="Synchronizer_SyncBlockProtection"></a>9.4. `Synchronizer.SyncBlockProtection`

**Type:** : `string`

**Default:** `"latest"`

**Description:** SyncBlockProtection specify the state to sync (lastest, finalized or safe)

**Example setting the default value** ("latest"):
```
[Synchronizer]
SyncBlockProtection="latest"
```

### <a name="Synchronizer_L1SyncCheckL2BlockHash"></a>9.5. `Synchronizer.L1SyncCheckL2BlockHash`

**Type:** : `boolean`

Expand All @@ -1413,7 +1428,7 @@ TrustedSequencerURL=""
L1SyncCheckL2BlockHash=true
```

### <a name="Synchronizer_L1SyncCheckL2BlockNumberhModulus"></a>9.5. `Synchronizer.L1SyncCheckL2BlockNumberhModulus`
### <a name="Synchronizer_L1SyncCheckL2BlockNumberhModulus"></a>9.6. `Synchronizer.L1SyncCheckL2BlockNumberhModulus`

**Type:** : `integer`

Expand All @@ -1428,7 +1443,7 @@ a modules 5, for instance, means check all l2block multiples of 5 (10,15,20,...)
L1SyncCheckL2BlockNumberhModulus=30
```

### <a name="Synchronizer_L1SynchronizationMode"></a>9.6. `Synchronizer.L1SynchronizationMode`
### <a name="Synchronizer_L1SynchronizationMode"></a>9.7. `Synchronizer.L1SynchronizationMode`

**Type:** : `enum (of string)`

Expand All @@ -1448,7 +1463,7 @@ Must be one of:
* "sequential"
* "parallel"

### <a name="Synchronizer_L1ParallelSynchronization"></a>9.7. `[Synchronizer.L1ParallelSynchronization]`
### <a name="Synchronizer_L1ParallelSynchronization"></a>9.8. `[Synchronizer.L1ParallelSynchronization]`

**Type:** : `object`
**Description:** L1ParallelSynchronization Configuration for parallel mode (if L1SynchronizationMode equal to 'parallel')
Expand All @@ -1466,7 +1481,7 @@ Must be one of:
| - [RollupInfoRetriesSpacing](#Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing ) | No | string | No | - | Duration |
| - [FallbackToSequentialModeOnSynchronized](#Synchronizer_L1ParallelSynchronization_FallbackToSequentialModeOnSynchronized ) | No | boolean | No | - | FallbackToSequentialModeOnSynchronized if true switch to sequential mode if the system is synchronized |

#### <a name="Synchronizer_L1ParallelSynchronization_MaxClients"></a>9.7.1. `Synchronizer.L1ParallelSynchronization.MaxClients`
#### <a name="Synchronizer_L1ParallelSynchronization_MaxClients"></a>9.8.1. `Synchronizer.L1ParallelSynchronization.MaxClients`

**Type:** : `integer`

Expand All @@ -1480,7 +1495,7 @@ Must be one of:
MaxClients=10
```

#### <a name="Synchronizer_L1ParallelSynchronization_MaxPendingNoProcessedBlocks"></a>9.7.2. `Synchronizer.L1ParallelSynchronization.MaxPendingNoProcessedBlocks`
#### <a name="Synchronizer_L1ParallelSynchronization_MaxPendingNoProcessedBlocks"></a>9.8.2. `Synchronizer.L1ParallelSynchronization.MaxPendingNoProcessedBlocks`

**Type:** : `integer`

Expand All @@ -1495,7 +1510,7 @@ sugested twice of NumberOfParallelOfEthereumClients
MaxPendingNoProcessedBlocks=25
```

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockPeriod"></a>9.7.3. `Synchronizer.L1ParallelSynchronization.RequestLastBlockPeriod`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockPeriod"></a>9.8.3. `Synchronizer.L1ParallelSynchronization.RequestLastBlockPeriod`

**Title:** Duration

Expand Down Expand Up @@ -1523,7 +1538,7 @@ This value only apply when the system is synchronized
RequestLastBlockPeriod="5s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning"></a>9.7.4. `[Synchronizer.L1ParallelSynchronization.PerformanceWarning]`
#### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning"></a>9.8.4. `[Synchronizer.L1ParallelSynchronization.PerformanceWarning]`

**Type:** : `object`
**Description:** Consumer Configuration for the consumer of rollup information from L1
Expand All @@ -1533,7 +1548,7 @@ RequestLastBlockPeriod="5s"
| - [AceptableInacctivityTime](#Synchronizer_L1ParallelSynchronization_PerformanceWarning_AceptableInacctivityTime ) | No | string | No | - | Duration |
| - [ApplyAfterNumRollupReceived](#Synchronizer_L1ParallelSynchronization_PerformanceWarning_ApplyAfterNumRollupReceived ) | No | integer | No | - | ApplyAfterNumRollupReceived is the number of iterations to<br />start checking the time waiting for new rollup info data |

##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_AceptableInacctivityTime"></a>9.7.4.1. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.AceptableInacctivityTime`
##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_AceptableInacctivityTime"></a>9.8.4.1. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.AceptableInacctivityTime`

**Title:** Duration

Expand Down Expand Up @@ -1562,7 +1577,7 @@ fast enought then you could increse the number of parallel clients to sync with
AceptableInacctivityTime="5s"
```

##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_ApplyAfterNumRollupReceived"></a>9.7.4.2. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.ApplyAfterNumRollupReceived`
##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_ApplyAfterNumRollupReceived"></a>9.8.4.2. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.ApplyAfterNumRollupReceived`

**Type:** : `integer`

Expand All @@ -1577,7 +1592,7 @@ start checking the time waiting for new rollup info data
ApplyAfterNumRollupReceived=10
```

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockTimeout"></a>9.7.5. `Synchronizer.L1ParallelSynchronization.RequestLastBlockTimeout`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockTimeout"></a>9.8.5. `Synchronizer.L1ParallelSynchronization.RequestLastBlockTimeout`

**Title:** Duration

Expand All @@ -1603,7 +1618,7 @@ ApplyAfterNumRollupReceived=10
RequestLastBlockTimeout="5s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockMaxRetries"></a>9.7.6. `Synchronizer.L1ParallelSynchronization.RequestLastBlockMaxRetries`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockMaxRetries"></a>9.8.6. `Synchronizer.L1ParallelSynchronization.RequestLastBlockMaxRetries`

**Type:** : `integer`

Expand All @@ -1617,7 +1632,7 @@ RequestLastBlockTimeout="5s"
RequestLastBlockMaxRetries=3
```

#### <a name="Synchronizer_L1ParallelSynchronization_StatisticsPeriod"></a>9.7.7. `Synchronizer.L1ParallelSynchronization.StatisticsPeriod`
#### <a name="Synchronizer_L1ParallelSynchronization_StatisticsPeriod"></a>9.8.7. `Synchronizer.L1ParallelSynchronization.StatisticsPeriod`

**Title:** Duration

Expand All @@ -1643,7 +1658,7 @@ RequestLastBlockMaxRetries=3
StatisticsPeriod="5m0s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_TimeOutMainLoop"></a>9.7.8. `Synchronizer.L1ParallelSynchronization.TimeOutMainLoop`
#### <a name="Synchronizer_L1ParallelSynchronization_TimeOutMainLoop"></a>9.8.8. `Synchronizer.L1ParallelSynchronization.TimeOutMainLoop`

**Title:** Duration

Expand All @@ -1669,7 +1684,7 @@ StatisticsPeriod="5m0s"
TimeOutMainLoop="5m0s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing"></a>9.7.9. `Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing`
#### <a name="Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing"></a>9.8.9. `Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing`

**Title:** Duration

Expand All @@ -1695,7 +1710,7 @@ TimeOutMainLoop="5m0s"
RollupInfoRetriesSpacing="5s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_FallbackToSequentialModeOnSynchronized"></a>9.7.10. `Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized`
#### <a name="Synchronizer_L1ParallelSynchronization_FallbackToSequentialModeOnSynchronized"></a>9.8.10. `Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized`

**Type:** : `boolean`

Expand All @@ -1709,7 +1724,7 @@ RollupInfoRetriesSpacing="5s"
FallbackToSequentialModeOnSynchronized=false
```

### <a name="Synchronizer_L2Synchronization"></a>9.8. `[Synchronizer.L2Synchronization]`
### <a name="Synchronizer_L2Synchronization"></a>9.9. `[Synchronizer.L2Synchronization]`

**Type:** : `object`
**Description:** L2Synchronization Configuration for L2 synchronization
Expand All @@ -1720,7 +1735,7 @@ FallbackToSequentialModeOnSynchronized=false
| - [ReprocessFullBatchOnClose](#Synchronizer_L2Synchronization_ReprocessFullBatchOnClose ) | No | boolean | No | - | ReprocessFullBatchOnClose if is true when a batch is closed is force to reprocess again |
| - [CheckLastL2BlockHashOnCloseBatch](#Synchronizer_L2Synchronization_CheckLastL2BlockHashOnCloseBatch ) | No | boolean | No | - | CheckLastL2BlockHashOnCloseBatch if is true when a batch is closed is force to check the last L2Block hash |

#### <a name="Synchronizer_L2Synchronization_AcceptEmptyClosedBatches"></a>9.8.1. `Synchronizer.L2Synchronization.AcceptEmptyClosedBatches`
#### <a name="Synchronizer_L2Synchronization_AcceptEmptyClosedBatches"></a>9.9.1. `Synchronizer.L2Synchronization.AcceptEmptyClosedBatches`

**Type:** : `boolean`

Expand All @@ -1735,7 +1750,7 @@ if true, the synchronizer will accept empty batches and process them.
AcceptEmptyClosedBatches=false
```

#### <a name="Synchronizer_L2Synchronization_ReprocessFullBatchOnClose"></a>9.8.2. `Synchronizer.L2Synchronization.ReprocessFullBatchOnClose`
#### <a name="Synchronizer_L2Synchronization_ReprocessFullBatchOnClose"></a>9.9.2. `Synchronizer.L2Synchronization.ReprocessFullBatchOnClose`

**Type:** : `boolean`

Expand All @@ -1749,7 +1764,7 @@ AcceptEmptyClosedBatches=false
ReprocessFullBatchOnClose=true
```

#### <a name="Synchronizer_L2Synchronization_CheckLastL2BlockHashOnCloseBatch"></a>9.8.3. `Synchronizer.L2Synchronization.CheckLastL2BlockHashOnCloseBatch`
#### <a name="Synchronizer_L2Synchronization_CheckLastL2BlockHashOnCloseBatch"></a>9.9.3. `Synchronizer.L2Synchronization.CheckLastL2BlockHashOnCloseBatch`

**Type:** : `boolean`

Expand Down
5 changes: 5 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,11 @@
"description": "TrustedSequencerURL is the rpc url to connect and sync the trusted state",
"default": ""
},
"SyncBlockProtection": {
"type": "string",
"description": "SyncBlockProtection specify the state to sync (lastest, finalized or safe)",
"default": "latest"
},
"L1SyncCheckL2BlockHash": {
"type": "boolean",
"description": "L1SyncCheckL2BlockHash if is true when a batch is closed is force to check L2Block hash against trustedNode (only apply for permissionless)",
Expand Down
1 change: 0 additions & 1 deletion etherman/etherman.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,6 @@ func (etherMan *Client) forcedBatchEvent(ctx context.Context, vLog types.Log, bl

func (etherMan *Client) sequencedBatchesEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error {
log.Debugf("SequenceBatches event detected: txHash: %s", common.Bytes2Hex(vLog.TxHash[:]))
//tx,isPending, err:=etherMan.EthClient.TransactionByHash(ctx, vLog.TxHash)

sb, err := etherMan.EtrogZkEVM.ParseSequenceBatches(vLog)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions synchronizer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type Config struct {
SyncChunkSize uint64 `mapstructure:"SyncChunkSize"`
// TrustedSequencerURL is the rpc url to connect and sync the trusted state
TrustedSequencerURL string `mapstructure:"TrustedSequencerURL"`
// SyncBlockProtection specify the state to sync (lastest, finalized or safe)
SyncBlockProtection string `mapstructure:"SyncBlockProtection"`

// L1SyncCheckL2BlockHash if is true when a batch is closed is force to check L2Block hash against trustedNode (only apply for permissionless)
L1SyncCheckL2BlockHash bool `mapstructure:"L1SyncCheckL2BlockHash"`
Expand Down
30 changes: 29 additions & 1 deletion synchronizer/synchronizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/0xPolygonHermez/zkevm-node/synchronizer/l2_sync/l2_sync_etrog"
"github.com/0xPolygonHermez/zkevm-node/synchronizer/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/jackc/pgx/v4"
)

Expand Down Expand Up @@ -53,6 +54,7 @@ type ClientSynchronizer struct {
latestFlushID uint64
// If true the lastFlushID is stored in DB and we don't need to check again
latestFlushIDIsFulfilled bool
syncBlockProtection rpc.BlockNumber
etherManForL1 []syncinterfaces.EthermanFullInterface
state syncinterfaces.StateFullInterface
pool syncinterfaces.PoolInterface
Expand Down Expand Up @@ -95,6 +97,13 @@ func NewSynchronizer(
runInDevelopmentMode bool) (Synchronizer, error) {
ctx, cancel := context.WithCancel(context.Background())
metrics.Register()
syncBlockProtection, err := decodeSyncBlockProtection(cfg.SyncBlockProtection)
if err != nil {
log.Errorf("error decoding syncBlockProtection. Error: %v", err)
cancel()
return nil, err
}
log.Info("syncBlockProtection: ", syncBlockProtection)
res := &ClientSynchronizer{
isTrustedSequencer: isTrustedSequencer,
state: st,
Expand All @@ -113,6 +122,7 @@ func NewSynchronizer(
previousExecutorFlushID: 0,
l1SyncOrchestration: nil,
l1EventProcessors: nil,
syncBlockProtection: syncBlockProtection,
halter: syncCommon.NewCriticalErrorHalt(eventLog, 5*time.Second), //nolint:gomnd
}
if !isTrustedSequencer {
Expand Down Expand Up @@ -169,6 +179,19 @@ func NewSynchronizer(
return res, nil
}

func decodeSyncBlockProtection(sBP string) (rpc.BlockNumber, error) {
switch sBP {
case "latest":
return rpc.LatestBlockNumber, nil
case "finalized":
return rpc.FinalizedBlockNumber, nil
case "safe":
return rpc.SafeBlockNumber, nil
default:
return 0, fmt.Errorf("error decoding SyncBlockProtection. Unknown value")
}
}

var waitDuration = time.Duration(0)

func newL1SyncParallel(ctx context.Context, cfg Config, etherManForL1 []syncinterfaces.EthermanFullInterface, sync *ClientSynchronizer, runExternalControl bool) *l1_parallel_sync.L1SyncOrchestration {
Expand Down Expand Up @@ -539,7 +562,7 @@ func (s *ClientSynchronizer) syncBlocksParallel(lastEthBlockSynced *state.Block)
// This function syncs the node from a specific block to the latest
func (s *ClientSynchronizer) syncBlocksSequential(lastEthBlockSynced *state.Block) (*state.Block, error) {
// Call the blockchain to retrieve data
header, err := s.etherMan.HeaderByNumber(s.ctx, nil)
header, err := s.etherMan.HeaderByNumber(s.ctx, big.NewInt(s.syncBlockProtection.Int64()))
if err != nil {
log.Error("error getting header of the latest block in L1. Error: ", err)
return lastEthBlockSynced, err
Expand Down Expand Up @@ -568,6 +591,9 @@ func (s *ClientSynchronizer) syncBlocksSequential(lastEthBlockSynced *state.Bloc

for {
toBlock := fromBlock + s.cfg.SyncChunkSize
if toBlock > lastKnownBlock.Uint64() {
toBlock = lastKnownBlock.Uint64()
}
log.Infof("Syncing block %d of %d", fromBlock, lastKnownBlock.Uint64())
log.Infof("Getting rollup info from block %d to block %d", fromBlock, toBlock)
// This function returns the rollup information contained in the ethereum blocks and an extra param called order.
Expand Down Expand Up @@ -721,6 +747,8 @@ func (s *ClientSynchronizer) checkReorg(latestBlock *state.Block) (*state.Block,
log.Errorf("error getting latest block synced from blockchain. Block: %d, error: %v", reorgedBlock.BlockNumber, err)
return nil, err
}
log.Infof("[checkReorg function] BlockNumber: %d BlockHash got from L1 provider: %s", block.Number().Uint64(), block.Hash().String())
log.Infof("[checkReorg function] latestBlockNumber: %d latestBlockHash already synced: %s", latestBlock.BlockNumber, latestBlock.BlockHash.String())
if block.NumberU64() != reorgedBlock.BlockNumber {
err = fmt.Errorf("wrong ethereum block retrieved from blockchain. Block numbers don't match. BlockNumber stored: %d. BlockNumber retrieved: %d",
reorgedBlock.BlockNumber, block.NumberU64())
Expand Down
Loading

0 comments on commit 09f9151

Please sign in to comment.