diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go index 74aed60c3b..1b23c11202 100644 --- a/aggregator/aggregator.go +++ b/aggregator/aggregator.go @@ -756,8 +756,23 @@ func (a *Aggregator) getAndLockBatchToProve(ctx context.Context, prover proverIn return nil, nil, err } + // Get header of the last L1 block + lastL1BlockHeader, err := a.Ethman.GetLatestBlockHeader(ctx) + if err != nil { + log.Errorf("Failed to get last L1 block header, err: %v", err) + return nil, nil, err + } + lastL1BlockNumber := lastL1BlockHeader.Number.Uint64() + + // Calculate max L1 block number for getting next virtual batch to prove + maxL1BlockNumber := uint64(0) + if a.cfg.BatchProofL1BlockConfirmations <= lastL1BlockNumber { + maxL1BlockNumber = lastL1BlockNumber - a.cfg.BatchProofL1BlockConfirmations + } + log.Debugf("Max L1 block number for getting next virtual batch to prove: %d", maxL1BlockNumber) + // Get virtual batch pending to generate proof - batchToVerify, err := a.State.GetVirtualBatchToProve(ctx, lastVerifiedBatch.BatchNumber, nil) + batchToVerify, err := a.State.GetVirtualBatchToProve(ctx, lastVerifiedBatch.BatchNumber, maxL1BlockNumber, nil) if err != nil { return nil, nil, err } diff --git a/aggregator/aggregator_test.go b/aggregator/aggregator_test.go index eb51a09381..a071828a16 100644 --- a/aggregator/aggregator_test.go +++ b/aggregator/aggregator_test.go @@ -17,6 +17,7 @@ import ( "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/test/testutils" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -775,7 +776,7 @@ func TestTryGenerateBatchProof(t *testing.T) { m.proverMock.On("ID").Return(proverID).Twice() m.proverMock.On("Addr").Return("addr") m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() - m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, mock.Anything, nil).Return(&batchToProve, nil).Once() m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( func(args mock.Arguments) { proof := args[1].(*state.Proof) @@ -798,6 +799,7 @@ func TestTryGenerateBatchProof(t *testing.T) { L1InfoRoot: &l1InfoRoot, TimestampBatchEtrog: &t, } + m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once() m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice() m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice() expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) @@ -817,7 +819,7 @@ func TestTryGenerateBatchProof(t *testing.T) { m.proverMock.On("ID").Return(proverID).Twice() m.proverMock.On("Addr").Return("addr") m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() - m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, mock.Anything, nil).Return(&batchToProve, nil).Once() m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( func(args mock.Arguments) { proof := args[1].(*state.Proof) @@ -840,6 +842,7 @@ func TestTryGenerateBatchProof(t *testing.T) { L1InfoRoot: &l1InfoRoot, TimestampBatchEtrog: &t, } + m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once() m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice() m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice() expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) @@ -860,7 +863,7 @@ func TestTryGenerateBatchProof(t *testing.T) { m.proverMock.On("ID").Return(proverID).Twice() m.proverMock.On("Addr").Return(proverID) m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() - m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, mock.Anything, nil).Return(&batchToProve, nil).Once() m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( func(args mock.Arguments) { proof := args[1].(*state.Proof) @@ -883,6 +886,7 @@ func TestTryGenerateBatchProof(t *testing.T) { L1InfoRoot: &l1InfoRoot, TimestampBatchEtrog: &t, } + m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once() m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice() m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice() expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) @@ -903,7 +907,7 @@ func TestTryGenerateBatchProof(t *testing.T) { m.proverMock.On("ID").Return(proverID).Times(3) m.proverMock.On("Addr").Return("addr") m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() - m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, mock.Anything, nil).Return(&batchToProve, nil).Once() m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( func(args mock.Arguments) { proof := args[1].(*state.Proof) @@ -926,6 +930,7 @@ func TestTryGenerateBatchProof(t *testing.T) { L1InfoRoot: &l1InfoRoot, TimestampBatchEtrog: &t, } + m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once() m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice() m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice() expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) @@ -960,7 +965,7 @@ func TestTryGenerateBatchProof(t *testing.T) { m.proverMock.On("ID").Return(proverID).Times(3) m.proverMock.On("Addr").Return("addr") m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() - m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, mock.Anything, nil).Return(&batchToProve, nil).Once() m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( func(args mock.Arguments) { proof := args[1].(*state.Proof) @@ -995,6 +1000,7 @@ func TestTryGenerateBatchProof(t *testing.T) { On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil). Return(&state.VerifiedBatch{BatchNumber: uint64(42)}, nil).Once() m.etherman.On("GetLatestVerifiedBatchNum").Return(uint64(42), nil).Once() + m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once() // make tryBuildFinalProof fail ASAP m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, errBanana).Once().NotBefore(isSyncedCall) m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), mock.Anything, nil).Run( diff --git a/aggregator/config.go b/aggregator/config.go index 9099df1931..420d6dcd2a 100644 --- a/aggregator/config.go +++ b/aggregator/config.go @@ -88,4 +88,7 @@ type Config struct { // UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog UpgradeEtrogBatchNumber uint64 `mapstructure:"UpgradeEtrogBatchNumber"` + + // BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch + BatchProofL1BlockConfirmations uint64 `mapstructure:"BatchProofL1BlockConfirmations"` } diff --git a/aggregator/interfaces.go b/aggregator/interfaces.go index 3bc9c2fe8a..0d6b11b7ed 100644 --- a/aggregator/interfaces.go +++ b/aggregator/interfaces.go @@ -9,6 +9,7 @@ import ( "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" ) @@ -39,6 +40,7 @@ type ethTxManager interface { type etherman interface { GetLatestVerifiedBatchNum() (uint64, error) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, inputs *ethmanTypes.FinalProofInputs, beneficiary common.Address) (to *common.Address, data []byte, err error) + GetLatestBlockHeader(ctx context.Context) (*types.Header, error) } // aggregatorTxProfitabilityChecker interface for different profitability @@ -53,7 +55,7 @@ type stateInterface interface { CheckProofContainsCompleteSequences(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) (bool, error) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) GetProofReadyToVerify(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Proof, error) - GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx) (*state.Batch, error) GetProofsToAggregate(ctx context.Context, dbTx pgx.Tx) (*state.Proof, *state.Proof, error) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) AddGeneratedProof(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) error diff --git a/aggregator/mocks/mock_etherman.go b/aggregator/mocks/mock_etherman.go index 4f0f97c61e..077771c339 100644 --- a/aggregator/mocks/mock_etherman.go +++ b/aggregator/mocks/mock_etherman.go @@ -3,7 +3,12 @@ package mocks import ( + context "context" + common "github.com/ethereum/go-ethereum/common" + + coretypes "github.com/ethereum/go-ethereum/core/types" + mock "github.com/stretchr/testify/mock" types "github.com/0xPolygonHermez/zkevm-node/etherman/types" @@ -53,6 +58,36 @@ func (_m *Etherman) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch uint64, ne return r0, r1, r2 } +// GetLatestBlockHeader provides a mock function with given fields: ctx +func (_m *Etherman) GetLatestBlockHeader(ctx context.Context) (*coretypes.Header, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetLatestBlockHeader") + } + + var r0 *coretypes.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*coretypes.Header, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *coretypes.Header); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Header) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetLatestVerifiedBatchNum provides a mock function with given fields: func (_m *Etherman) GetLatestVerifiedBatchNum() (uint64, error) { ret := _m.Called() diff --git a/aggregator/mocks/mock_state.go b/aggregator/mocks/mock_state.go index 24b2ffd61e..cfc5b66e7d 100644 --- a/aggregator/mocks/mock_state.go +++ b/aggregator/mocks/mock_state.go @@ -454,9 +454,9 @@ func (_m *StateMock) GetVirtualBatchParentHash(ctx context.Context, batchNumber return r0, r1 } -// GetVirtualBatchToProve provides a mock function with given fields: ctx, lastVerfiedBatchNumber, dbTx -func (_m *StateMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { - ret := _m.Called(ctx, lastVerfiedBatchNumber, dbTx) +// GetVirtualBatchToProve provides a mock function with given fields: ctx, lastVerfiedBatchNumber, maxL1Block, dbTx +func (_m *StateMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) if len(ret) == 0 { panic("no return value specified for GetVirtualBatchToProve") @@ -464,19 +464,19 @@ func (_m *StateMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatc var r0 *state.Batch var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { - return rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { - r0 = rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*state.Batch) } } - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } else { r1 = ret.Error(1) } diff --git a/config/config_test.go b/config/config_test.go index a031f88a68..2efaaf0616 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -477,6 +477,10 @@ func Test_Defaults(t *testing.T) { path: "Aggregator.UpgradeEtrogBatchNumber", expectedValue: uint64(0), }, + { + path: "Aggregator.BatchProofL1BlockConfirmations", + expectedValue: uint64(2), + }, { path: "State.Batch.Constraints.MaxTxsPerBatch", expectedValue: uint64(300), diff --git a/config/default.go b/config/default.go index a18586be4e..4bca8b1c9a 100644 --- a/config/default.go +++ b/config/default.go @@ -164,6 +164,7 @@ CleanupLockedProofsInterval = "2m" GeneratingProofCleanupThreshold = "10m" GasOffset = 0 UpgradeEtrogBatchNumber = 0 +BatchProofL1BlockConfirmations = 2 [L2GasPriceSuggester] Type = "follower" diff --git a/config/environments/local/local.node.config.toml b/config/environments/local/local.node.config.toml index ebf5b2544d..9fefe6362b 100644 --- a/config/environments/local/local.node.config.toml +++ b/config/environments/local/local.node.config.toml @@ -128,6 +128,7 @@ SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" CleanupLockedProofsInterval = "2m" GeneratingProofCleanupThreshold = "10m" UpgradeEtrogBatchNumber = 0 +BatchProofL1BlockConfirmations = 2 [EthTxManager] ForcedGas = 0 diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html index 8f9e04279a..f578dbcd6a 100644 --- a/docs/config-file/node-config-doc.html +++ b/docs/config-file/node-config-doc.html @@ -66,7 +66,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


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:


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 37a3d6563a..249daf8660 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -2370,6 +2370,7 @@ GasOffset=80000
 | - [GeneratingProofCleanupThreshold](#Aggregator_GeneratingProofCleanupThreshold )                   | No      | string  | No         | -          | GeneratingProofCleanupThreshold represents the time interval after
which a proof in generating state is considered to be stuck and
allowed to be cleared. | | - [GasOffset](#Aggregator_GasOffset ) | No | integer | No | - | 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 | | - [UpgradeEtrogBatchNumber](#Aggregator_UpgradeEtrogBatchNumber ) | No | integer | No | - | UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog | +| - [BatchProofL1BlockConfirmations](#Aggregator_BatchProofL1BlockConfirmations ) | No | integer | No | - | BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch | ### 12.1. `Aggregator.Host` @@ -2647,6 +2648,20 @@ GasOffset=0 UpgradeEtrogBatchNumber=0 ``` +### 12.16. `Aggregator.BatchProofL1BlockConfirmations` + +**Type:** : `integer` + +**Default:** `2` + +**Description:** BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch + +**Example setting the default value** (2): +``` +[Aggregator] +BatchProofL1BlockConfirmations=2 +``` + ## 13. `[NetworkConfig]` **Type:** : `object` diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json index b28e8ea462..95e2e2b248 100644 --- a/docs/config-file/node-config-schema.json +++ b/docs/config-file/node-config-schema.json @@ -1011,6 +1011,11 @@ "type": "integer", "description": "UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog", "default": 0 + }, + "BatchProofL1BlockConfirmations": { + "type": "integer", + "description": "BatchProofL1BlockConfirmations is number of L1 blocks to consider we can generate the proof for a virtual batch", + "default": 2 } }, "additionalProperties": false, diff --git a/state/interfaces.go b/state/interfaces.go index 17636f5ce1..f6b5859a80 100644 --- a/state/interfaces.go +++ b/state/interfaces.go @@ -98,7 +98,7 @@ type storage interface { GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*GlobalExitRoot, error) AddSequence(ctx context.Context, sequence Sequence, dbTx pgx.Tx) error GetSequences(ctx context.Context, lastVerifiedBatchNumber uint64, dbTx pgx.Tx) ([]Sequence, error) - GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*Batch, error) + GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx) (*Batch, error) CheckProofContainsCompleteSequences(ctx context.Context, proof *Proof, dbTx pgx.Tx) (bool, error) GetProofReadyToVerify(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*Proof, error) GetProofsToAggregate(ctx context.Context, dbTx pgx.Tx) (*Proof, *Proof, error) diff --git a/state/mocks/mock_storage.go b/state/mocks/mock_storage.go index 559e73a930..4856aa7e41 100644 --- a/state/mocks/mock_storage.go +++ b/state/mocks/mock_storage.go @@ -6950,9 +6950,9 @@ func (_c *StorageMock_GetVirtualBatchParentHash_Call) RunAndReturn(run func(cont return _c } -// GetVirtualBatchToProve provides a mock function with given fields: ctx, lastVerfiedBatchNumber, dbTx -func (_m *StorageMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { - ret := _m.Called(ctx, lastVerfiedBatchNumber, dbTx) +// GetVirtualBatchToProve provides a mock function with given fields: ctx, lastVerfiedBatchNumber, maxL1Block, dbTx +func (_m *StorageMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) if len(ret) == 0 { panic("no return value specified for GetVirtualBatchToProve") @@ -6960,19 +6960,19 @@ func (_m *StorageMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBa var r0 *state.Batch var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { - return rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { - r0 = rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*state.Batch) } } - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, lastVerfiedBatchNumber, dbTx) + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, lastVerfiedBatchNumber, maxL1Block, dbTx) } else { r1 = ret.Error(1) } @@ -6988,14 +6988,15 @@ type StorageMock_GetVirtualBatchToProve_Call struct { // GetVirtualBatchToProve is a helper method to define mock.On call // - ctx context.Context // - lastVerfiedBatchNumber uint64 +// - maxL1Block uint64 // - dbTx pgx.Tx -func (_e *StorageMock_Expecter) GetVirtualBatchToProve(ctx interface{}, lastVerfiedBatchNumber interface{}, dbTx interface{}) *StorageMock_GetVirtualBatchToProve_Call { - return &StorageMock_GetVirtualBatchToProve_Call{Call: _e.mock.On("GetVirtualBatchToProve", ctx, lastVerfiedBatchNumber, dbTx)} +func (_e *StorageMock_Expecter) GetVirtualBatchToProve(ctx interface{}, lastVerfiedBatchNumber interface{}, maxL1Block interface{}, dbTx interface{}) *StorageMock_GetVirtualBatchToProve_Call { + return &StorageMock_GetVirtualBatchToProve_Call{Call: _e.mock.On("GetVirtualBatchToProve", ctx, lastVerfiedBatchNumber, maxL1Block, dbTx)} } -func (_c *StorageMock_GetVirtualBatchToProve_Call) Run(run func(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx)) *StorageMock_GetVirtualBatchToProve_Call { +func (_c *StorageMock_GetVirtualBatchToProve_Call) Run(run func(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx)) *StorageMock_GetVirtualBatchToProve_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(pgx.Tx)) + run(args[0].(context.Context), args[1].(uint64), args[2].(uint64), args[3].(pgx.Tx)) }) return _c } @@ -7005,7 +7006,7 @@ func (_c *StorageMock_GetVirtualBatchToProve_Call) Return(_a0 *state.Batch, _a1 return _c } -func (_c *StorageMock_GetVirtualBatchToProve_Call) RunAndReturn(run func(context.Context, uint64, pgx.Tx) (*state.Batch, error)) *StorageMock_GetVirtualBatchToProve_Call { +func (_c *StorageMock_GetVirtualBatchToProve_Call) RunAndReturn(run func(context.Context, uint64, uint64, pgx.Tx) (*state.Batch, error)) *StorageMock_GetVirtualBatchToProve_Call { _c.Call.Return(run) return _c } diff --git a/state/pgstatestorage/batch.go b/state/pgstatestorage/batch.go index 214be8a685..83bfad3cdb 100644 --- a/state/pgstatestorage/batch.go +++ b/state/pgstatestorage/batch.go @@ -764,7 +764,7 @@ func (p *PostgresStorage) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) // GetVirtualBatchToProve return the next batch that is not proved, neither in // proved process. -func (p *PostgresStorage) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { +func (p *PostgresStorage) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, maxL1Block uint64, dbTx pgx.Tx) (*state.Batch, error) { const query = ` SELECT b.batch_num, @@ -783,6 +783,7 @@ func (p *PostgresStorage) GetVirtualBatchToProve(ctx context.Context, lastVerfie state.virtual_batch v WHERE b.batch_num > $1 AND b.batch_num = v.batch_num AND + v.block_num <= $2 AND NOT EXISTS ( SELECT p.batch_num FROM state.proof p WHERE v.batch_num >= p.batch_num AND v.batch_num <= p.batch_num_final @@ -790,7 +791,7 @@ func (p *PostgresStorage) GetVirtualBatchToProve(ctx context.Context, lastVerfie ORDER BY b.batch_num ASC LIMIT 1 ` e := p.getExecQuerier(dbTx) - row := e.QueryRow(ctx, query, lastVerfiedBatchNumber) + row := e.QueryRow(ctx, query, lastVerfiedBatchNumber, maxL1Block) batch, err := scanBatch(row) if errors.Is(err, pgx.ErrNoRows) { return nil, state.ErrNotFound diff --git a/test/config/debug.node.config.toml b/test/config/debug.node.config.toml index aa1a5f5ee0..32bbdd7f56 100644 --- a/test/config/debug.node.config.toml +++ b/test/config/debug.node.config.toml @@ -129,6 +129,7 @@ SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" CleanupLockedProofsInterval = "2m" GeneratingProofCleanupThreshold = "10m" UpgradeEtrogBatchNumber = 0 +BatchProofL1BlockConfirmations = 2 [EthTxManager] ForcedGas = 0 diff --git a/test/config/test.node.config.toml b/test/config/test.node.config.toml index 76c6e53aee..8d6a0d215d 100644 --- a/test/config/test.node.config.toml +++ b/test/config/test.node.config.toml @@ -146,6 +146,7 @@ SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" CleanupLockedProofsInterval = "2m" GeneratingProofCleanupThreshold = "10m" UpgradeEtrogBatchNumber = 0 +BatchProofL1BlockConfirmations = 2 [EthTxManager] ForcedGas = 0