diff --git a/cmd/run.go b/cmd/run.go index e3043558b7..24fa2861ab 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -119,15 +119,8 @@ func start(cliCtx *cli.Context) error { log.Fatal(err) } - st := newState(cliCtx.Context, c, l2ChainID, []state.ForkIDInterval{}, stateSqlDB, eventLog, needsExecutor, needsStateTree) - forkIDIntervals, err := forkIDIntervals(cliCtx.Context, st, etherman, c.NetworkConfig.Genesis.BlockNumber) - if err != nil { - log.Fatal("error getting forkIDs. Error: ", err) - } - st.UpdateForkIDIntervalsInMemory(forkIDIntervals) + st, currentForkID := newState(cliCtx.Context, c, etherman, l2ChainID, stateSqlDB, eventLog, needsExecutor, needsStateTree, false) - currentForkID := forkIDIntervals[len(forkIDIntervals)-1].ForkId - log.Infof("Fork ID read from POE SC = %v", forkIDIntervals[len(forkIDIntervals)-1].ForkId) c.Aggregator.ChainID = l2ChainID c.Sequencer.StreamServer.ChainID = l2ChainID log.Infof("Chain ID read from POE SC = %v", l2ChainID) @@ -212,6 +205,7 @@ func start(cliCtx *cli.Context) error { for _, a := range cliCtx.StringSlice(config.FlagHTTPAPI) { apis[a] = true } + st, _ := newState(cliCtx.Context, c, etherman, l2ChainID, stateSqlDB, eventLog, needsExecutor, needsStateTree, true) go runJSONRPCServer(*c, etherman, l2ChainID, poolInstance, st, apis) case SYNCHRONIZER: ev.Component = event.Component_Synchronizer @@ -459,7 +453,7 @@ func waitSignal(cancelFuncs []context.CancelFunc) { } } -func newState(ctx context.Context, c *config.Config, l2ChainID uint64, forkIDIntervals []state.ForkIDInterval, sqlDB *pgxpool.Pool, eventLog *event.EventLog, needsExecutor, needsStateTree bool) *state.State { +func newState(ctx context.Context, c *config.Config, etherman *etherman.Client, l2ChainID uint64, sqlDB *pgxpool.Pool, eventLog *event.EventLog, needsExecutor, needsStateTree, avoidForkIDInMemory bool) (*state.State, uint64) { stateDb := pgstatestorage.NewPostgresStorage(c.State, sqlDB) // Executor @@ -478,7 +472,7 @@ func newState(ctx context.Context, c *config.Config, l2ChainID uint64, forkIDInt stateCfg := state.Config{ MaxCumulativeGasUsed: c.State.Batch.Constraints.MaxCumulativeGasUsed, ChainID: l2ChainID, - ForkIDIntervals: forkIDIntervals, + ForkIDIntervals: []state.ForkIDInterval{}, MaxResourceExhaustedAttempts: c.Executor.MaxResourceExhaustedAttempts, WaitOnResourceExhaustion: c.Executor.WaitOnResourceExhaustion, ForkUpgradeBatchNumber: c.ForkUpgradeBatchNumber, @@ -486,6 +480,7 @@ func newState(ctx context.Context, c *config.Config, l2ChainID uint64, forkIDInt MaxLogsCount: c.RPC.MaxLogsCount, MaxLogsBlockRange: c.RPC.MaxLogsBlockRange, MaxNativeBlockHashBlockRange: c.RPC.MaxNativeBlockHashBlockRange, + AvoidForkIDInMemory: avoidForkIDInMemory, } allLeaves, err := stateDb.GetAllL1InfoRootEntries(ctx, nil) if err != nil { @@ -501,7 +496,17 @@ func newState(ctx context.Context, c *config.Config, l2ChainID uint64, forkIDInt } st := state.NewState(stateCfg, stateDb, executorClient, stateTree, eventLog, mt) - return st + + forkIDIntervals, err := forkIDIntervals(ctx, st, etherman, c.NetworkConfig.Genesis.BlockNumber) + if err != nil { + log.Fatal("error getting forkIDs. Error: ", err) + } + st.UpdateForkIDIntervalsInMemory(forkIDIntervals) + + currentForkID := forkIDIntervals[len(forkIDIntervals)-1].ForkId + log.Infof("Fork ID read from POE SC = %v", forkIDIntervals[len(forkIDIntervals)-1].ForkId) + + return st, currentForkID } func createPool(cfgPool pool.Config, constraintsCfg state.BatchConstraintsCfg, l2ChainID uint64, st *state.State, eventLog *event.EventLog) *pool.Pool { diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html index 33c937c2dd..111fb8018b 100644 --- a/docs/config-file/node-config-doc.html +++ b/docs/config-file/node-config-doc.html @@ -76,4 +76,4 @@
"300ms"
 

Default: 100000000Type: integer

Configuration of the merkle tree client service. Not use in the node, only for testing
Default: "zkevm-prover:50061"Type: string

URI is the server URI.


Configuration of the metrics service, basically is where is going to publish the metrics
Default: "0.0.0.0"Type: string

Host is the address to bind the metrics server


Default: 9091Type: integer

Port is the port to bind the metrics server


Default: falseType: boolean

Enabled is the flag to enable/disable the metrics server


Default: ""Type: string

ProfilingHost is the address to bind the profiling server


Default: 0Type: integer

ProfilingPort is the port to bind the profiling server


Default: falseType: boolean

ProfilingEnabled is the flag to enable/disable the profiling server


Configuration of the event database connection

DB is the database configuration
Default: ""Type: string

Database name


Default: ""Type: string

Database User name


Default: ""Type: string

Database Password of the user


Default: ""Type: string

Host address of database


Default: ""Type: string

Port Number of database


Default: falseType: boolean

EnableLog


Default: 0Type: integer

MaxConns is the maximum number of connections in the pool.


Configuration of the hash database connection
Default: "prover_db"Type: string

Database name


Default: "prover_user"Type: string

Database User name


Default: "prover_pass"Type: string

Database Password of the user


Default: "zkevm-state-db"Type: string

Host address of database


Default: "5432"Type: string

Port Number of database


Default: falseType: boolean

EnableLog


Default: 200Type: integer

MaxConns is the maximum number of connections in the pool.


State service configuration
Default: 0Type: integer

MaxCumulativeGasUsed is the max gas allowed per batch


Default: 0Type: integer

ChainID is the L2 ChainID provided by the Network Config


Type: array of object

ForkIdIntervals is the list of fork id intervals

Each item of this array must be:


Default: 0Type: integer

MaxResourceExhaustedAttempts is the max number of attempts to make a transaction succeed because of resource exhaustion


Default: "0s"Type: string

WaitOnResourceExhaustion is the time to wait before retrying a transaction because of resource exhaustion


Examples:

"1m"
 
"300ms"
-

Default: 0Type: integer

Batch number from which there is a forkid change (fork upgrade)


Default: 0Type: integer

New fork id to be used for batches greaters than ForkUpgradeBatchNumber (fork upgrade)


DB is the database configuration
Default: "state_db"Type: string

Database name


Default: "state_user"Type: string

Database User name


Default: "state_password"Type: string

Database Password of the user


Default: "zkevm-state-db"Type: string

Host address of database


Default: "5432"Type: string

Port Number of database


Default: falseType: boolean

EnableLog


Default: 200Type: integer

MaxConns is the maximum number of connections in the pool.


Configuration for the batch constraints
Default: 300Type: integer

Default: 120000Type: integer

Default: 9223372036854775807Type: integer

Default: 2145Type: integer

Default: 252357Type: integer

Default: 135191Type: integer

Default: 236585Type: integer

Default: 236585Type: integer

Default: 473170Type: integer

Default: 7570538Type: integer

Default: 1596Type: integer

Default: 0Type: integer

MaxLogsCount is a configuration to set the max number of logs that can be returned
in a single call to the state, if zero it means no limit


Default: 0Type: integer

MaxLogsBlockRange is a configuration to set the max range for block number when querying TXs
logs in a single call to the state, if zero it means no limit


Default: 0Type: integer

MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying
native block hashes in a single call to the state, if zero it means no limit


\ No newline at end of file +
Default: 0Type: integer

Batch number from which there is a forkid change (fork upgrade)


Default: 0Type: integer

New fork id to be used for batches greaters than ForkUpgradeBatchNumber (fork upgrade)


DB is the database configuration
Default: "state_db"Type: string

Database name


Default: "state_user"Type: string

Database User name


Default: "state_password"Type: string

Database Password of the user


Default: "zkevm-state-db"Type: string

Host address of database


Default: "5432"Type: string

Port Number of database


Default: falseType: boolean

EnableLog


Default: 200Type: integer

MaxConns is the maximum number of connections in the pool.


Configuration for the batch constraints
Default: 300Type: integer

Default: 120000Type: integer

Default: 9223372036854775807Type: integer

Default: 2145Type: integer

Default: 252357Type: integer

Default: 135191Type: integer

Default: 236585Type: integer

Default: 236585Type: integer

Default: 473170Type: integer

Default: 7570538Type: integer

Default: 1596Type: integer

Default: 0Type: integer

MaxLogsCount is a configuration to set the max number of logs that can be returned
in a single call to the state, if zero it means no limit


Default: 0Type: integer

MaxLogsBlockRange is a configuration to set the max range for block number when querying TXs
logs in a single call to the state, if zero it means no limit


Default: 0Type: integer

MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying
native block hashes in a single call to the state, if zero it means no limit


Default: falseType: boolean

AvoidForkIDInMemory is a configuration that forces the ForkID information to be loaded
from the DB every time it's needed


\ No newline at end of file diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md index aeed594674..e6a97716a9 100644 --- a/docs/config-file/node-config-doc.md +++ b/docs/config-file/node-config-doc.md @@ -3420,6 +3420,7 @@ MaxConns=200 | - [MaxLogsCount](#State_MaxLogsCount ) | No | integer | No | - | MaxLogsCount is a configuration to set the max number of logs that can be returned
in a single call to the state, if zero it means no limit | | - [MaxLogsBlockRange](#State_MaxLogsBlockRange ) | No | integer | No | - | MaxLogsBlockRange is a configuration to set the max range for block number when querying TXs
logs in a single call to the state, if zero it means no limit | | - [MaxNativeBlockHashBlockRange](#State_MaxNativeBlockHashBlockRange ) | No | integer | No | - | MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying
native block hashes in a single call to the state, if zero it means no limit | +| - [AvoidForkIDInMemory](#State_AvoidForkIDInMemory ) | No | boolean | No | - | AvoidForkIDInMemory is a configuration that forces the ForkID information to be loaded
from the DB every time it's needed | ### 20.1. `State.MaxCumulativeGasUsed` @@ -3884,5 +3885,20 @@ native block hashes in a single call to the state, if zero it means no limit MaxNativeBlockHashBlockRange=0 ``` +### 20.13. `State.AvoidForkIDInMemory` + +**Type:** : `boolean` + +**Default:** `false` + +**Description:** AvoidForkIDInMemory is a configuration that forces the ForkID information to be loaded +from the DB every time it's needed + +**Example setting the default value** (false): +``` +[State] +AvoidForkIDInMemory=false +``` + ---------------------------------------------------------------------------------------------------------------------------- Generated using [json-schema-for-humans](https://github.com/coveooss/json-schema-for-humans) diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json index c694202bf3..9c1f305445 100644 --- a/docs/config-file/node-config-schema.json +++ b/docs/config-file/node-config-schema.json @@ -1541,6 +1541,11 @@ "type": "integer", "description": "MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying\nnative block hashes in a single call to the state, if zero it means no limit", "default": 0 + }, + "AvoidForkIDInMemory": { + "type": "boolean", + "description": "AvoidForkIDInMemory is a configuration that forces the ForkID information to be loaded\nfrom the DB every time it's needed", + "default": false } }, "additionalProperties": false, diff --git a/state/config.go b/state/config.go index 554d739792..598b65681b 100644 --- a/state/config.go +++ b/state/config.go @@ -45,6 +45,10 @@ type Config struct { // MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying // native block hashes in a single call to the state, if zero it means no limit MaxNativeBlockHashBlockRange uint64 + + // AvoidForkIDInMemory is a configuration that forces the ForkID information to be loaded + // from the DB every time it's needed + AvoidForkIDInMemory bool } // BatchConfig represents the configuration of the batch constraints diff --git a/state/pgstatestorage/forkid.go b/state/pgstatestorage/forkid.go index 0eca2d430a..a53d083638 100644 --- a/state/pgstatestorage/forkid.go +++ b/state/pgstatestorage/forkid.go @@ -105,6 +105,32 @@ func (p *PostgresStorage) AddForkIDInterval(ctx context.Context, newForkID state // GetForkIDByBlockNumber returns the fork id for a given block number func (p *PostgresStorage) GetForkIDByBlockNumber(blockNumber uint64) uint64 { + if p.cfg.AvoidForkIDInMemory { + const query = ` + SELECT fork_id + FROM state.fork_id + WHERE block_num < $1 + ORDER BY fork_id DESC + LIMIT 1` + q := p.getExecQuerier(nil) + + var forkID uint64 + err := q.QueryRow(context.Background(), query, blockNumber).Scan(&forkID) + if errors.Is(err, pgx.ErrNoRows) { + return 1 + } else if err != nil { + log.Warnf("failed to get forkID by blockNumber from db, falling back to in memory information, err: %v", err) + return p.GetForkIDByBlockNumberInMemory(blockNumber) + } + + return forkID + } else { + return p.GetForkIDByBlockNumberInMemory(blockNumber) + } +} + +// GetForkIDByBlockNumber returns the fork id for a given block number in memory +func (p *PostgresStorage) GetForkIDByBlockNumberInMemory(blockNumber uint64) uint64 { for _, index := range sortIndexForForkdIDSortedByBlockNumber(p.cfg.ForkIDIntervals) { // reverse travesal interval := p.cfg.ForkIDIntervals[len(p.cfg.ForkIDIntervals)-1-index] @@ -130,6 +156,44 @@ func sortIndexForForkdIDSortedByBlockNumber(forkIDs []state.ForkIDInterval) []in // GetForkIDByBatchNumber returns the fork id for a given batch number func (p *PostgresStorage) GetForkIDByBatchNumber(batchNumber uint64) uint64 { + if p.cfg.AvoidForkIDInMemory { + const query = ` + SELECT fork_id FROM state.fork_id + WHERE from_batch_num <= $1 AND to_batch_num >= $1 + ORDER BY fork_id DESC + LIMIT 1` + q := p.getExecQuerier(nil) + + var forkID uint64 + err := q.QueryRow(context.Background(), query, batchNumber).Scan(&forkID) + if errors.Is(err, pgx.ErrNoRows) { + const query = ` + SELECT fork_id + FROM state.fork_id + ORDER BY fork_id DESC + LIMIT 1` + q := p.getExecQuerier(nil) + err := q.QueryRow(context.Background(), query).Scan(&forkID) + if errors.Is(err, pgx.ErrNoRows) { + log.Warnf("can't find forkID by batchNumber in the db, falling back to in memory information, err: %v", err) + return p.GetForkIDByBatchNumberInMemory(batchNumber) + } else if err != nil { + log.Warnf("failed to get forkID by batchNumber from db, falling back to in memory information, err: %v", err) + return p.GetForkIDByBatchNumberInMemory(batchNumber) + } + } else if err != nil { + log.Warnf("failed to get forkID by batchNumber from db, falling back to in memory information, err: %v", err) + return p.GetForkIDByBatchNumberInMemory(batchNumber) + } + + return forkID + } else { + return p.GetForkIDByBatchNumberInMemory(batchNumber) + } +} + +// GetForkIDByBatchNumberInMemory returns the fork id for a given batch number +func (p *PostgresStorage) GetForkIDByBatchNumberInMemory(batchNumber uint64) uint64 { // If NumBatchForkIdUpgrade is defined (!=0) we are performing forkid upgrade process // In this case, if the batchNumber is the next to the NumBatchForkIdUpgrade, we need to return the // new "future" forkId (ForkUpgradeNewForkId)