Skip to content

Commit

Permalink
synchronizer accepts empty closed batches from trusted depending on c…
Browse files Browse the repository at this point in the history
…onfig (#3370)

* accept empty closed batches depending on config
* if trusted synchronization dont create L2 sync classes
  • Loading branch information
joanestebanr committed Feb 27, 2024
1 parent cd4c30c commit 93d581b
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 27 deletions.
4 changes: 4 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ func Test_Defaults(t *testing.T) {
path: "Synchronizer.L1ParallelSynchronization.MaxPendingNoProcessedBlocks",
expectedValue: uint64(25),
},
{
path: "Synchronizer.L2Synchronization.AcceptEmptyClosedBatches",
expectedValue: false,
},
{
path: "Sequencer.DeletePoolTxsL1BlockConfirmations",
expectedValue: uint64(100),
Expand Down
2 changes: 2 additions & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ L1SynchronizationMode = "sequential"
[Synchronizer.L1ParallelSynchronization.PerformanceWarning]
AceptableInacctivityTime = "5s"
ApplyAfterNumRollupReceived = 10
[Synchronizer.L2Synchronization]
AcceptEmptyClosedBatches = false
[Sequencer]
DeletePoolTxsL1BlockConfirmations = 100
Expand Down
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</pre></div> </div><div id=Synchronizer_L1ParallelSynchronization_TimeOutMainLoop_ex2 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;300ms&quot;</span>
</pre></div> </div> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><!-- None --><a href=#Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing onclick="anchorLink('Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing')">Synchronizer.L1ParallelSynchronization.RollupInfoRetriesSpacing=</a> </div> <span class="badge badge-success default-value">Default: "5s"</span><span class="badge badge-dark value-type">Type: string</span><br> <span class=description><p>RollupInfoRetriesSpacing is the minimum time between retries to request rollup info (it will sleep for fulfill this time) to avoid spamming L1</p> </span> <br> <div class="badge badge-secondary">Examples:</div> <br><div id=Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing_ex1 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;1m&quot;</span>
</pre></div> </div><div id=Synchronizer_L1ParallelSynchronization_RollupInfoRetriesSpacing_ex2 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;300ms&quot;</span>
</pre></div> </div> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><!-- None --><a href=#Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized onclick="anchorLink('Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized')">Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized=</a> </div> <span class="badge badge-success default-value">Default: false</span><span class="badge badge-dark value-type">Type: boolean</span><br> <span class=description><p>FallbackToSequentialModeOnSynchronized if true switch to sequential mode if the system is synchronized</p> </span> <hr> </div> </div> </div> </div> </div> </div> </div> </div> <div class=accordion id=accordionSequencer> <div class=card> <div class=card-header id=headingSequencer> <h2 class=mb-0> <button class="btn btn-link property-name-button" type=button data-toggle=collapse data-target=#Sequencer aria-expanded aria-controls=Sequencer onclick="setAnchor('#Sequencer')"><span class=property-name> <div class=breadcrumbs>[<a href=#Sequencer onclick="anchorLink('Sequencer')">Sequencer</a>] </div></span></button> </h2> Configuration of the sequencer service </div> <div id=Sequencer class="collapse property-definition-div" aria-labelledby=headingSequencer data-parent=#accordionSequencer> <div class="card-body pl-5"> <div class=breadcrumbs> <!-- None --><!-- None --><a href=#Sequencer.DeletePoolTxsL1BlockConfirmations onclick="anchorLink('Sequencer.DeletePoolTxsL1BlockConfirmations')">Sequencer.DeletePoolTxsL1BlockConfirmations=</a> </div> <span class="badge badge-success default-value">Default: 100</span><span class="badge badge-dark value-type">Type: integer</span><br> <span class=description><p>DeletePoolTxsL1BlockConfirmations is blocks amount after which txs will be deleted from the pool</p> </span> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><a href=#Sequencer.DeletePoolTxsCheckInterval onclick="anchorLink('Sequencer.DeletePoolTxsCheckInterval')">Sequencer.DeletePoolTxsCheckInterval=</a> </div> <span class="badge badge-success default-value">Default: "12h0m0s"</span><span class="badge badge-dark value-type">Type: string</span><br> <span class=description><p>DeletePoolTxsCheckInterval is frequency with which txs will be checked for deleting</p> </span> <br> <div class="badge badge-secondary">Examples:</div> <br><div id=Sequencer_DeletePoolTxsCheckInterval_ex1 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;1m&quot;</span>
</pre></div> </div> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><!-- None --><a href=#Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized onclick="anchorLink('Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized')">Synchronizer.L1ParallelSynchronization.FallbackToSequentialModeOnSynchronized=</a> </div> <span class="badge badge-success default-value">Default: false</span><span class="badge badge-dark value-type">Type: boolean</span><br> <span class=description><p>FallbackToSequentialModeOnSynchronized if true switch to sequential mode if the system is synchronized</p> </span> <hr> </div> </div> </div> </div> <div class=accordion id=accordionSynchronizer_L2Synchronization> <div class=card> <div class=card-header id=headingSynchronizer_L2Synchronization> <h2 class=mb-0> <button class="btn btn-link property-name-button" type=button data-toggle=collapse data-target=#Synchronizer_L2Synchronization aria-expanded aria-controls=Synchronizer_L2Synchronization onclick="setAnchor('#Synchronizer_L2Synchronization')"><span class=property-name> <div class=breadcrumbs>[<a href=#Synchronizer onclick="anchorLink('Synchronizer')">Synchronizer</a> . <a href=#Synchronizer_L2Synchronization onclick="anchorLink('Synchronizer_L2Synchronization')">L2Synchronization</a>] </div></span></button> </h2> L2Synchronization Configuration for L2 synchronization </div> <div id=Synchronizer_L2Synchronization class="collapse property-definition-div" aria-labelledby=headingSynchronizer_L2Synchronization data-parent=#accordionSynchronizer_L2Synchronization> <div class="card-body pl-5"> <div class=breadcrumbs> <!-- None --><!-- None --><!-- None --><a href=#Synchronizer.L2Synchronization.AcceptEmptyClosedBatches onclick="anchorLink('Synchronizer.L2Synchronization.AcceptEmptyClosedBatches')">Synchronizer.L2Synchronization.AcceptEmptyClosedBatches=</a> </div> <span class="badge badge-success default-value">Default: false</span><span class="badge badge-dark value-type">Type: boolean</span><br> <span class=description><p>AcceptEmptyClosedBatches is a flag to enable or disable the acceptance of empty batches.<br> if true, the synchronizer will accept empty batches and process them.</p> </span> <hr> </div> </div> </div> </div> </div> </div> </div> </div> <div class=accordion id=accordionSequencer> <div class=card> <div class=card-header id=headingSequencer> <h2 class=mb-0> <button class="btn btn-link property-name-button" type=button data-toggle=collapse data-target=#Sequencer aria-expanded aria-controls=Sequencer onclick="setAnchor('#Sequencer')"><span class=property-name> <div class=breadcrumbs>[<a href=#Sequencer onclick="anchorLink('Sequencer')">Sequencer</a>] </div></span></button> </h2> Configuration of the sequencer service </div> <div id=Sequencer class="collapse property-definition-div" aria-labelledby=headingSequencer data-parent=#accordionSequencer> <div class="card-body pl-5"> <div class=breadcrumbs> <!-- None --><!-- None --><a href=#Sequencer.DeletePoolTxsL1BlockConfirmations onclick="anchorLink('Sequencer.DeletePoolTxsL1BlockConfirmations')">Sequencer.DeletePoolTxsL1BlockConfirmations=</a> </div> <span class="badge badge-success default-value">Default: 100</span><span class="badge badge-dark value-type">Type: integer</span><br> <span class=description><p>DeletePoolTxsL1BlockConfirmations is blocks amount after which txs will be deleted from the pool</p> </span> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><a href=#Sequencer.DeletePoolTxsCheckInterval onclick="anchorLink('Sequencer.DeletePoolTxsCheckInterval')">Sequencer.DeletePoolTxsCheckInterval=</a> </div> <span class="badge badge-success default-value">Default: "12h0m0s"</span><span class="badge badge-dark value-type">Type: string</span><br> <span class=description><p>DeletePoolTxsCheckInterval is frequency with which txs will be checked for deleting</p> </span> <br> <div class="badge badge-secondary">Examples:</div> <br><div id=Sequencer_DeletePoolTxsCheckInterval_ex1 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;1m&quot;</span>
</pre></div> </div><div id=Sequencer_DeletePoolTxsCheckInterval_ex2 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;300ms&quot;</span>
</pre></div> </div> <hr> <div class=breadcrumbs> <!-- None --><!-- None --><a href=#Sequencer.TxLifetimeCheckInterval onclick="anchorLink('Sequencer.TxLifetimeCheckInterval')">Sequencer.TxLifetimeCheckInterval=</a> </div> <span class="badge badge-success default-value">Default: "10m0s"</span><span class="badge badge-dark value-type">Type: string</span><br> <span class=description><p>TxLifetimeCheckInterval is the time the sequencer waits to check txs lifetime</p> </span> <br> <div class="badge badge-secondary">Examples:</div> <br><div id=Sequencer_TxLifetimeCheckInterval_ex1 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;1m&quot;</span>
</pre></div> </div><div id=Sequencer_TxLifetimeCheckInterval_ex2 class="jumbotron examples"><div class=highlight><pre><span></span><span class=s2>&quot;300ms&quot;</span>
Expand Down
25 changes: 25 additions & 0 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,7 @@ because depending of this values is going to ask to a trusted node for trusted t
| - [TrustedSequencerURL](#Synchronizer_TrustedSequencerURL ) | No | string | No | - | TrustedSequencerURL is the rpc url to connect and sync the trusted state |
| - [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 |

### <a name="Synchronizer_SyncInterval"></a>9.1. `Synchronizer.SyncInterval`

Expand Down Expand Up @@ -1677,6 +1678,30 @@ RollupInfoRetriesSpacing="5s"
FallbackToSequentialModeOnSynchronized=false
```

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

**Type:** : `object`
**Description:** L2Synchronization Configuration for L2 synchronization

| Property | Pattern | Type | Deprecated | Definition | Title/Description |
| --------------------------------------------------------------------------------------- | ------- | ------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - [AcceptEmptyClosedBatches](#Synchronizer_L2Synchronization_AcceptEmptyClosedBatches ) | No | boolean | No | - | AcceptEmptyClosedBatches is a flag to enable or disable the acceptance of empty batches.<br />if true, the synchronizer will accept empty batches and process them. |

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

**Type:** : `boolean`

**Default:** `false`

**Description:** AcceptEmptyClosedBatches is a flag to enable or disable the acceptance of empty batches.
if true, the synchronizer will accept empty batches and process them.

**Example setting the default value** (false):
```
[Synchronizer.L2Synchronization]
AcceptEmptyClosedBatches=false
```

## <a name="Sequencer"></a>10. `[Sequencer]`

**Type:** : `object`
Expand Down
12 changes: 12 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,18 @@
"additionalProperties": false,
"type": "object",
"description": "L1ParallelSynchronization Configuration for parallel mode (if L1SynchronizationMode equal to 'parallel')"
},
"L2Synchronization": {
"properties": {
"AcceptEmptyClosedBatches": {
"type": "boolean",
"description": "AcceptEmptyClosedBatches is a flag to enable or disable the acceptance of empty batches.\nif true, the synchronizer will accept empty batches and process them.",
"default": false
}
},
"additionalProperties": false,
"type": "object",
"description": "L2Synchronization Configuration for L2 synchronization"
}
},
"additionalProperties": false,
Expand Down
25 changes: 25 additions & 0 deletions jsonrpc/client/zkevm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package client

import (
"context"
"fmt"
"math/big"
"testing"

"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/stretchr/testify/require"
)

func TestZkevmGetBatch(t *testing.T) {
t.Skip("This test is exploratory")
// Create a new client
client := NewClient("https://zkevm-rpc.com/")
lastTrustedStateBatchNumberSeen, err := client.BatchNumber(context.Background())
require.NoError(t, err)
log.Info("lastTrustedStateBatchNumberSeen: ", lastTrustedStateBatchNumberSeen)
batch, err := client.BatchByNumber(context.Background(), big.NewInt(int64(lastTrustedStateBatchNumberSeen)))
require.NoError(t, err)

// Print the batch
fmt.Println(batch)
}
3 changes: 3 additions & 0 deletions synchronizer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package synchronizer

import (
"github.com/0xPolygonHermez/zkevm-node/config/types"
"github.com/0xPolygonHermez/zkevm-node/synchronizer/l2_sync"
)

// Config represents the configuration of the synchronizer
Expand All @@ -19,6 +20,8 @@ type Config struct {
L1SynchronizationMode string `jsonschema:"enum=sequential,enum=parallel"`
// L1ParallelSynchronization Configuration for parallel mode (if L1SynchronizationMode equal to 'parallel')
L1ParallelSynchronization L1ParallelSynchronizationConfig
// L2Synchronization Configuration for L2 synchronization
L2Synchronization l2_sync.Config `mapstructure:"L2Synchronization"`
}

// L1ParallelSynchronizationConfig Configuration for parallel mode (if UL1SynchronizationMode equal to 'parallel')
Expand Down
8 changes: 8 additions & 0 deletions synchronizer/l2_sync/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package l2_sync

// Config configuration of L2 sync process
type Config struct {
// AcceptEmptyClosedBatches is a flag to enable or disable the acceptance of empty batches.
// if true, the synchronizer will accept empty batches and process them.
AcceptEmptyClosedBatches bool `mapstructure:"AcceptEmptyClosedBatches"`
}
36 changes: 30 additions & 6 deletions synchronizer/l2_sync/l2_shared/processor_trusted_batch_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/state"
syncCommon "github.com/0xPolygonHermez/zkevm-node/synchronizer/common"
"github.com/0xPolygonHermez/zkevm-node/synchronizer/l2_sync"
"github.com/ethereum/go-ethereum/common"
"github.com/jackc/pgx/v4"
)
Expand Down Expand Up @@ -124,8 +125,6 @@ type SyncTrustedBatchExecutor interface {
ReProcess(ctx context.Context, data *ProcessData, dbTx pgx.Tx) (*ProcessResponse, error)
// NothingProcess process a batch that is already synchronized, so we don't need to process it
NothingProcess(ctx context.Context, data *ProcessData, dbTx pgx.Tx) (*ProcessResponse, error)
// CloseBatch close a batch
//CloseBatch(ctx context.Context, trustedBatch *types.Batch, dbTx pgx.Tx) error
}

// ProcessorTrustedBatchSync is a template to sync trusted state. It classify what kind of update is needed and call to SyncTrustedStateBatchExecutorSteps
Expand All @@ -136,14 +135,16 @@ type SyncTrustedBatchExecutor interface {
type ProcessorTrustedBatchSync struct {
Steps SyncTrustedBatchExecutor
timeProvider syncCommon.TimeProvider
Cfg l2_sync.Config
}

// NewProcessorTrustedBatchSync creates a new SyncTrustedStateBatchExecutorTemplate
func NewProcessorTrustedBatchSync(steps SyncTrustedBatchExecutor,
timeProvider syncCommon.TimeProvider) *ProcessorTrustedBatchSync {
timeProvider syncCommon.TimeProvider, cfg l2_sync.Config) *ProcessorTrustedBatchSync {
return &ProcessorTrustedBatchSync{
Steps: steps,
timeProvider: timeProvider,
Cfg: cfg,
}
}

Expand Down Expand Up @@ -265,7 +266,7 @@ func (s *ProcessorTrustedBatchSync) GetModeForProcessBatch(trustedNodeBatch *typ
return ProcessData{}, fmt.Errorf("trustedNodeBatch and statePreviousBatch can't be nil")
}

var result ProcessData
var result ProcessData = ProcessData{}
if stateBatch == nil {
result = ProcessData{
Mode: FullProcessMode,
Expand Down Expand Up @@ -308,23 +309,40 @@ func (s *ProcessorTrustedBatchSync) GetModeForProcessBatch(trustedNodeBatch *typ
}
}
}

if result.Mode == "" {
return result, fmt.Errorf("failed to get mode for process batch %v", trustedNodeBatch.Number)
return result, fmt.Errorf("batch %v: failed to get mode for process ", trustedNodeBatch.Number)
}

result.BatchNumber = uint64(trustedNodeBatch.Number)
result.StateBatch = stateBatch
result.TrustedBatch = trustedNodeBatch
result.PreviousStateBatch = statePreviousBatch
result.OldAccInputHash = statePreviousBatch.AccInputHash
result.Now = s.timeProvider.Now()
result.DebugPrefix = fmt.Sprintf("%s mode %s:", debugPrefix, result.Mode)

if isTrustedBatchEmptyAndClosed(trustedNodeBatch) {
if s.Cfg.AcceptEmptyClosedBatches {
log.Infof("%s Batch %v: TrustedBatch Empty and closed, accepted due configuration", result.DebugPrefix, trustedNodeBatch.Number)
} else {
err := fmt.Errorf("%s Batch %v: TrustedBatch Empty and closed, rejected due configuration", result.DebugPrefix, trustedNodeBatch.Number)
log.Infof(err.Error())
return result, err
}
}

return result, nil
}

func isTrustedBatchClosed(batch *types.Batch) bool {
return batch.Closed
}

func isTrustedBatchEmptyAndClosed(batch *types.Batch) bool {
return len(batch.BatchL2Data) == 0 && isTrustedBatchClosed(batch)
}

func checkStateRootAndLER(batchNumber uint64, expectedStateRoot common.Hash, expectedLER common.Hash, calculatedStateRoot common.Hash, calculatedLER common.Hash) error {
if calculatedStateRoot != expectedStateRoot {
return fmt.Errorf("batch %v: stareRoot calculated [%s] is different from the one in the batch [%s] err:%w", batchNumber, calculatedStateRoot, expectedStateRoot, ErrFatalBatchDesynchronized)
Expand All @@ -339,7 +357,13 @@ func checkProcessBatchResultMatchExpected(data *ProcessData, processBatchResp *s
var err error = nil
var trustedBatch = data.TrustedBatch
if trustedBatch == nil {
panic("trustedBatch is nil")
err = fmt.Errorf("%s trustedBatch is nil, it never should be nil", data.DebugPrefix)
log.Error(err.Error())
return err
}
if len(trustedBatch.BatchL2Data) == 0 {
log.Warnf("Batch %v: BatchL2Data is empty, no checking", trustedBatch.Number)
return nil
}
if processBatchResp == nil {
log.Warnf("Batch %v: Can't check processBatchResp because is nil, then check store batch in DB", trustedBatch.Number)
Expand Down
Loading

0 comments on commit 93d581b

Please sign in to comment.