Skip to content

Commit

Permalink
Fork8/0xPolygonHermez#3544 sync block protection (#121)
Browse files Browse the repository at this point in the history
* Add sync block protection

* Add sync block protection

* Add sync block protection

* Remove elderberry sanity check

* Minor change

---------

Co-authored-by: Stefan Negovanović <[email protected]>
  • Loading branch information
arnaubennassar and Stefan-Ethernal authored Apr 9, 2024
1 parent 29fe2c7 commit 4bb2522
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 74 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 = "safe" # latest, finalized, safe
L1SynchronizationMode = "sequential"
[Synchronizer.L1ParallelSynchronization]
MaxClients = 10
Expand Down
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

51 changes: 33 additions & 18 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) |
| - [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 |
| - [L1ParallelSynchronization](#Synchronizer_L1ParallelSynchronization ) | No | object | No | - | L1ParallelSynchronization Configuration for parallel mode (if L1SynchronizationMode equal to 'parallel') |
| - [L2Synchronization](#Synchronizer_L2Synchronization ) | No | object | No | - | L2Synchronization Configuration for L2 synchronization |
Expand Down Expand Up @@ -1397,7 +1398,21 @@ SyncChunkSize=100
TrustedSequencerURL=""
```

### <a name="Synchronizer_L1SynchronizationMode"></a>9.4. `Synchronizer.L1SynchronizationMode`
### <a name="Synchronizer_SyncBlockProtection"></a>9.4. `Synchronizer.SyncBlockProtection`

**Type:** : `string`

**Default:** `"safe"`

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

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

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

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

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

### <a name="Synchronizer_L1ParallelSynchronization"></a>9.5. `[Synchronizer.L1ParallelSynchronization]`
### <a name="Synchronizer_L1ParallelSynchronization"></a>9.6. `[Synchronizer.L1ParallelSynchronization]`

**Type:** : `object`
**Description:** L1ParallelSynchronization Configuration for parallel mode (if L1SynchronizationMode equal to 'parallel')
Expand All @@ -1435,7 +1450,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.5.1. `Synchronizer.L1ParallelSynchronization.MaxClients`
#### <a name="Synchronizer_L1ParallelSynchronization_MaxClients"></a>9.6.1. `Synchronizer.L1ParallelSynchronization.MaxClients`

**Type:** : `integer`

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

#### <a name="Synchronizer_L1ParallelSynchronization_MaxPendingNoProcessedBlocks"></a>9.5.2. `Synchronizer.L1ParallelSynchronization.MaxPendingNoProcessedBlocks`
#### <a name="Synchronizer_L1ParallelSynchronization_MaxPendingNoProcessedBlocks"></a>9.6.2. `Synchronizer.L1ParallelSynchronization.MaxPendingNoProcessedBlocks`

**Type:** : `integer`

Expand All @@ -1464,7 +1479,7 @@ sugested twice of NumberOfParallelOfEthereumClients
MaxPendingNoProcessedBlocks=25
```

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockPeriod"></a>9.5.3. `Synchronizer.L1ParallelSynchronization.RequestLastBlockPeriod`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockPeriod"></a>9.6.3. `Synchronizer.L1ParallelSynchronization.RequestLastBlockPeriod`

**Title:** Duration

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

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

**Type:** : `object`
**Description:** Consumer Configuration for the consumer of rollup information from L1
Expand All @@ -1502,7 +1517,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.5.4.1. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.AceptableInacctivityTime`
##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_AceptableInacctivityTime"></a>9.6.4.1. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.AceptableInacctivityTime`

**Title:** Duration

Expand Down Expand Up @@ -1531,7 +1546,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.5.4.2. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.ApplyAfterNumRollupReceived`
##### <a name="Synchronizer_L1ParallelSynchronization_PerformanceWarning_ApplyAfterNumRollupReceived"></a>9.6.4.2. `Synchronizer.L1ParallelSynchronization.PerformanceWarning.ApplyAfterNumRollupReceived`

**Type:** : `integer`

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

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockTimeout"></a>9.5.5. `Synchronizer.L1ParallelSynchronization.RequestLastBlockTimeout`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockTimeout"></a>9.6.5. `Synchronizer.L1ParallelSynchronization.RequestLastBlockTimeout`

**Title:** Duration

Expand All @@ -1572,7 +1587,7 @@ ApplyAfterNumRollupReceived=10
RequestLastBlockTimeout="5s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockMaxRetries"></a>9.5.6. `Synchronizer.L1ParallelSynchronization.RequestLastBlockMaxRetries`
#### <a name="Synchronizer_L1ParallelSynchronization_RequestLastBlockMaxRetries"></a>9.6.6. `Synchronizer.L1ParallelSynchronization.RequestLastBlockMaxRetries`

**Type:** : `integer`

Expand All @@ -1586,7 +1601,7 @@ RequestLastBlockTimeout="5s"
RequestLastBlockMaxRetries=3
```

#### <a name="Synchronizer_L1ParallelSynchronization_StatisticsPeriod"></a>9.5.7. `Synchronizer.L1ParallelSynchronization.StatisticsPeriod`
#### <a name="Synchronizer_L1ParallelSynchronization_StatisticsPeriod"></a>9.6.7. `Synchronizer.L1ParallelSynchronization.StatisticsPeriod`

**Title:** Duration

Expand All @@ -1612,7 +1627,7 @@ RequestLastBlockMaxRetries=3
StatisticsPeriod="5m0s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_TimeOutMainLoop"></a>9.5.8. `Synchronizer.L1ParallelSynchronization.TimeOutMainLoop`
#### <a name="Synchronizer_L1ParallelSynchronization_TimeOutMainLoop"></a>9.6.8. `Synchronizer.L1ParallelSynchronization.TimeOutMainLoop`

**Title:** Duration

Expand All @@ -1638,7 +1653,7 @@ StatisticsPeriod="5m0s"
TimeOutMainLoop="5m0s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing"></a>9.5.9. `Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing`
#### <a name="Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing"></a>9.6.9. `Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing`

**Title:** Duration

Expand All @@ -1664,7 +1679,7 @@ TimeOutMainLoop="5m0s"
RollupInfoRetriesSpacing="5s"
```

#### <a name="Synchronizer_L1ParallelSynchronization_FallbackToSequentialModeOnSynchronized"></a>9.5.10. `Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized`
#### <a name="Synchronizer_L1ParallelSynchronization_FallbackToSequentialModeOnSynchronized"></a>9.6.10. `Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized`

**Type:** : `boolean`

Expand All @@ -1678,7 +1693,7 @@ RollupInfoRetriesSpacing="5s"
FallbackToSequentialModeOnSynchronized=false
```

### <a name="Synchronizer_L2Synchronization"></a>9.6. `[Synchronizer.L2Synchronization]`
### <a name="Synchronizer_L2Synchronization"></a>9.7. `[Synchronizer.L2Synchronization]`

**Type:** : `object`
**Description:** L2Synchronization Configuration for L2 synchronization
Expand All @@ -1689,7 +1704,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.6.1. `Synchronizer.L2Synchronization.AcceptEmptyClosedBatches`
#### <a name="Synchronizer_L2Synchronization_AcceptEmptyClosedBatches"></a>9.7.1. `Synchronizer.L2Synchronization.AcceptEmptyClosedBatches`

**Type:** : `boolean`

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

#### <a name="Synchronizer_L2Synchronization_ReprocessFullBatchOnClose"></a>9.6.2. `Synchronizer.L2Synchronization.ReprocessFullBatchOnClose`
#### <a name="Synchronizer_L2Synchronization_ReprocessFullBatchOnClose"></a>9.7.2. `Synchronizer.L2Synchronization.ReprocessFullBatchOnClose`

**Type:** : `boolean`

Expand All @@ -1718,7 +1733,7 @@ AcceptEmptyClosedBatches=false
ReprocessFullBatchOnClose=false
```

#### <a name="Synchronizer_L2Synchronization_CheckLastL2BlockHashOnCloseBatch"></a>9.6.3. `Synchronizer.L2Synchronization.CheckLastL2BlockHashOnCloseBatch`
#### <a name="Synchronizer_L2Synchronization_CheckLastL2BlockHashOnCloseBatch"></a>9.7.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": "safe"
},
"L1SynchronizationMode": {
"type": "string",
"enum": [
Expand Down
57 changes: 5 additions & 52 deletions synchronizer/actions/elderberry/processor_l1_sequence_batches.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package elderberry
import (
"context"
"errors"
"fmt"
"time"

"github.com/0xPolygonHermez/zkevm-node/etherman"
Expand Down Expand Up @@ -59,59 +58,13 @@ func (g *ProcessorL1SequenceBatchesElderberry) Process(ctx context.Context, orde
}

sbatch := l1Block.SequencedBatches[order.Pos][0]
executionTime := l1Block.ReceivedAt

if sbatch.SequencedBatchElderberryData == nil {
log.Errorf("No elderberry sequenced batch data for batch %d", sbatch.BatchNumber)
return fmt.Errorf("no elderberry sequenced batch data for batch %d", sbatch.BatchNumber)
log.Warnf("No elderberry sequenced batch data for batch %d", sbatch.BatchNumber)
} else {
executionTime = time.Unix(int64(sbatch.SequencedBatchElderberryData.MaxSequenceTimestamp), 0)
}
// We need to check that the sequence match
err := g.sanityCheckExpectedSequence(sbatch.SequencedBatchElderberryData.InitSequencedBatchNumber, dbTx)
if err != nil {
return err
}
// We known that the MaxSequenceTimestamp is the same for all the batches so we can use the first one
err = g.previousProcessor.ProcessSequenceBatches(ctx, l1Block.SequencedBatches[order.Pos], l1Block.BlockNumber, time.Unix(int64(sbatch.SequencedBatchElderberryData.MaxSequenceTimestamp), 0), dbTx)
// The last L2block timestamp must match MaxSequenceTimestamp
if err != nil {
return err
}
// It checks the timestamp of the last L2 block, but it's just log an error instead of refusing the event
_ = g.sanityCheckTstampLastL2Block(sbatch.SequencedBatchElderberryData.MaxSequenceTimestamp, dbTx)
return nil
}

func (g *ProcessorL1SequenceBatchesElderberry) sanityCheckExpectedSequence(initialBatchNumber uint64, dbTx pgx.Tx) error {
// We need to check that the sequence match
lastVirtualBatchNum, err := g.state.GetLastVirtualBatchNum(context.Background(), dbTx)
if err != nil {
log.Errorf("Error getting last virtual batch number: %s", err)
return err
}
if lastVirtualBatchNum != initialBatchNumber {
log.Errorf("The last virtual batch number is not the expected one. Expected: %d (last on DB), got: %d (L1 event)", lastVirtualBatchNum+1, initialBatchNumber)
return fmt.Errorf("the last virtual batch number is not the expected one. Expected: %d (last on DB), got: %d (L1 event) err:%w", lastVirtualBatchNum+1, initialBatchNumber, ErrInvalidInitialBatchNumber)
}
return nil
}

func (g *ProcessorL1SequenceBatchesElderberry) sanityCheckTstampLastL2Block(timeLimit uint64, dbTx pgx.Tx) error {
lastVirtualBatchNum, err := g.state.GetLastVirtualBatchNum(context.Background(), dbTx)
if err != nil {
log.Errorf("Error getting last virtual batch number: %s", err)
return err
}
lastL2Block, err := g.state.GetLastL2BlockByBatchNumber(context.Background(), lastVirtualBatchNum, dbTx)
if err != nil {
log.Errorf("Error getting last virtual batch number: %s", err)
return err
}
if lastL2Block == nil {
//TODO: find the previous batch until we find a L2 block to check the timestamp
return nil
}
if uint64(lastL2Block.ReceivedAt.Unix()) > timeLimit {
log.Errorf("The last L2 block timestamp can't be greater than timeLimit. Expected: %d (L1 event), got: %d (last L2Block)", timeLimit, lastL2Block.ReceivedAt.Unix())
return fmt.Errorf("wrong timestamp of last L2 block timestamp with L1 event timestamp")
}
return nil
return g.previousProcessor.ProcessSequenceBatches(ctx, l1Block.SequencedBatches[order.Pos], l1Block.BlockNumber, executionTime, dbTx)
}
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"`

// L1SynchronizationMode define how to synchronize with L1:
// - parallel: Request data to L1 in parallel, and process sequentially. The advantage is that executor is not blocked waiting for L1 data
Expand Down
Loading

0 comments on commit 4bb2522

Please sign in to comment.