Mainnet Updates

This document is only applicable for upgrading self-built nodes that are synchronizing normally. For new rpc node setup please refer to "External Node Deployment".

Release notes

Upgrade Schedule

  • Date and Time: Starting on May 24 at 3 PM (GMT + 8), estimated to last about 12 hours.

Upgrade Details

  • Upgrade the Polygon CDK version from fork5 to fork8.

  • Support for precompiled contracts: SHA256, ecAdd, ecMul, ecPairing.

  • Significant performance improvements for AA wallet transactions.

  • Support for multiple transactions within a single block.

  • Optimized external node data synchronization efficiency.

  • Each block will have its own timestamp.

Impact of the Upgrade

  • During the upgrade, Merlin Chain will suspend block production.

  • Official nodes will support normal reading of historical data but will not be able to receive or process new transaction requests.

  • The official cross-chain bridge will be temporarily unavailable.

  • The Particle wallet will be unavailable on Merlin Chain.

  • All external self-built nodes need to upgrade their node programs after the official notification of a successful upgrade.

  • All external RPC interfaces will be operational after the upgrade, with no changes to the RPC interface specifications.

  • The browser will remain operational during the upgrade.

Before maintenance

New version configuration

  • docker-compose.yml

version: "3.5"
networks:
  default:
    name: merlin-rpc-network

services:
  cdk-validium-state-db:
    container_name: merlin-state-db
    restart: unless-stopped
    image: postgres:15
    cpu_shares: 4096
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=state_user
      - POSTGRES_PASSWORD=state_password
      - POSTGRES_DB=state_db
    volumes:
      - ./init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql
      - /data/merlin/data/statedb:/var/lib/postgresql/data
    command:
      - "postgres"
      - "-N"
      - "500"
      - "-c"
      - "max_connections=20000"
      - "-c"
      - "shared_buffers=16GB"
      - "-c"
      - "work_mem=32MB"
      - "-c"
      - "wal_buffers=8MB"
      - "-c"
      - "effective_cache_size=16GB"
      - "-c"
      - "maintenance_work_mem=128MB"
      - "-c"
      - "checkpoint_completion_target=0.7"
      - "-c"
      - "max_wal_size=4GB"
      - "-c"
      - "min_wal_size=200MB"
      - "-c"
      - "max_worker_processes=16"

  cdk-validium-pool-db:
    container_name: merlin-pool-db
    restart: unless-stopped
    image: postgres:15
    cpu_shares: 4096
    ports:
      - 5433:5432
    environment:
      - POSTGRES_USER=pool_user
      - POSTGRES_PASSWORD=pool_password
      - POSTGRES_DB=pool_db
    volumes:
      - /data/merlin/data/pooldb:/var/lib/postgresql/data
    command:
      - "postgres"
      - "-N"
      - "500"
      - "-c"
      - "max_connections=10000"

  cdk-validium-prover:
    container_name: merlin-prover
    image: merlinadmin/zkprover:v5.0.9
    restart: unless-stopped
    logging:
      options:
        max-size: '500m'
        max-file: '3'
    ports:
      - 50061:50061 # MT
      - 50071:50071 # Executor
    volumes:
      - ./prover.config.json:/usr/src/app/config.json
    command: >
      zkProver -c /usr/src/app/config.json

  cdk-validium-sync:
    container_name: merlin-sync
    image: merlinadmin/zkevm-node:v2.1.1
    restart: unless-stopped
    logging:
      options:
        max-size: '500m'
        max-file: '3'
    ports:
      - 9091:9091
    volumes:
      - ./node.config.toml:/app/config.toml
      - ./genesis.json:/app/genesis.json
    command:
      - "/bin/sh"
      - "-c"
      - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components synchronizer"

  cdk-validium-json-rpc:
    container_name: merlin-rpc
    image: merlinadmin/zkevm-node:v2.1.1
    restart: unless-stopped
    logging:
      options:
        max-size: '500m'
        max-file: '5'
    ports:
      - 8123:8123
      #- 8133:8133 # needed if WebSockets enabled
      #- 9092:9091 # needed if metrics enabled
    volumes:
      - ./node.config.toml:/app/config.toml
      - ./genesis.json:/app/genesis.json
    command:
      - "/bin/sh"
      - "-c"
      - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components rpc --http.api eth,net,debug,zkevm,txpool,web3" #with debug mode. delete "--http.api eth,net,debug,zkevm,txpool,web3" will remove debug endpoint.
  • genesis-new.json

Will be available after the upgrade starts.

wget https://download.merlinchain.io/merlin/mainnet/genesis-new.json -O genesis.json
  • node.config.toml

UpgradeEtrogBatchNumber will also be confirmed after the RPC mainnet upgrade begins. 
IsTrustedSequencer = false

[Log]
Environment = "production" # "production" or "development"
Level = "info"
Outputs = ["stderr"]

[Synchronizer]
SyncInterval = "1s"
SyncChunkSize = 300
SyncOnlyTrusted = false # set to "false" will support zkevm_isBlockConsolidated and zkevm_consolidatedBlockNumber
TrustedSequencerURL = "https://rpc.merlinchain.io" # Keep the URL consistent with the original configuration.
L1SynchronizationMode = "parallel"
UpgradeEtrogBatchNumber = 1642245

[Synchronizer.L1ParallelSynchronization]
MaxClients = 10
MaxPendingNoProcessedBlocks = 25
RequestLastBlockPeriod = "5s"
RequestLastBlockTimeout = "5s"
RequestLastBlockMaxRetries = 3
StatisticsPeriod = "5m"
TimeoutMainLoop = "5m"
RollupInfoRetriesSpacing = "5s"
FallbackToSequentialModeOnSynchronized = false

[Synchronizer.L1ParallelSynchronization.PerformanceWarning]
AceptableInacctivityTime = "5s"
ApplyAfterNumRollupReceived = 10

[Etherman]
URL = "http://18.142.49.94:8545"
ForkIDChunkSize = 20000
MultiGasProvider = false

[RPC]
Host = "0.0.0.0"
Port = 8123
ReadTimeout = "60s"
WriteTimeout = "60s"
MaxRequestsPerIPAndSecond = 10000
SequencerNodeURI = "https://rpc.merlinchain.io" # Keep the URL consistent with the original configuration.
EnableL2SuggestedGasPricePolling = false
TraceBatchUseHTTPS = true
BatchRequestsEnabled = true
BatchRequestsLimit = 10000

[RPC.WebSockets]
Enabled = true
Host = "0.0.0.0"
Port = 8133

[State]
[State.DB]
User = "state_user"
Password = "state_password"
Name = "state_db"
Host = "merlin-state-db"
Port = "5432"
EnableLog = false
MaxConns = 800

[State.Batch]
[State.Batch.Constraints]
MaxTxsPerBatch = 300
MaxBatchBytesSize = 120000
MaxCumulativeGasUsed = 1125899906842624
MaxKeccakHashes = 2145
MaxPoseidonHashes = 252357
MaxPoseidonPaddings = 135191
MaxMemAligns = 236585
MaxArithmetics = 236585
MaxBinaries = 473170
MaxSteps = 7570538
MaxSHA256Hashes = 1596

[Pool]
FreeClaimGasLimit = 1500000
IntervalToRefreshBlockedAddresses = "5m"
IntervalToRefreshGasPrices = "5s"
MaxTxBytesSize = 100132
MaxTxDataBytesSize = 100000
DefaultMinGasPriceAllowed = 50000000
MinAllowedGasPriceInterval = "5m"
PollMinAllowedGasPriceInterval = "15s"
AccountQueue = 100
GlobalQueue = 10240

[Pool.EffectiveGasPrice]
Enabled = false
L1GasPriceFactor = 0.25
ByteGasCost = 16
ZeroByteGasCost = 4
NetProfit = 1
BreakEvenFactor = 1.1
FinalDeviationPct = 10
EthTransferGasPrice = 0
EthTransferL1GasPriceFactor = 0
L2GasPriceSuggesterFactor = 0.5

[Pool.DB]
User = "pool_user"
Password = "pool_password"
Name = "pool_db"
Host = "merlin-pool-db"
Port = "5432"
EnableLog = false
MaxConns = 800

[Metrics]
Host = "0.0.0.0"
Port = 9091
Enabled = true
ProfilingHost = "0.0.0.0"
ProfilingPort = 6060
ProfilingEnabled = true

[MTClient]
URI = "cdk-validium-prover:50061"

[Executor]
URI = "cdk-validium-prover:50071"
MaxResourceExhaustedAttempts = 5
WaitOnResourceExhaustion = "1s"
MaxGRPCMessageSize = 300000000
  • prover.config.json

{
  "configPath": "/usr/src/app/config",
  "runExecutorServer": true,
  "runExecutorClient": false,
  "runExecutorClientMultithread": false,
  "runHashDBServer": true,
  "runHashDBTest": false,
  "runAggregatorServer": false,
  "runAggregatorClient": false,
  "runFileGenBatchProof": false,
  "runFileGenAggregatedProof": false,
  "runFileGenFinalProof": false,
  "runFileProcessBatch": false,
  "runFileProcessBatchMultithread": false,
  "runKeccakScriptGenerator": false,
  "runKeccakTest": false,
  "runStorageSMTest": false,
  "runBinarySMTest": false,
  "runMemAlignSMTest": false,
  "runSHA256Test": false,
  "runBlakeTest": false,
  "executeInParallel": true,
  "useMainExecGenerated": true,
  "saveRequestToFile": false,
  "saveInputToFile": false,
  "saveDbReadsToFile": false,
  "saveDbReadsToFileOnChange": false,
  "saveOutputToFile": true,
  "saveProofToFile": true,
  "saveResponseToFile": false,
  "loadDBToMemCache": true,
  "opcodeTracer": false,
  "logRemoteDbReads": false,
  "logExecutorServerResponses": false,
  "proverServerPort": 50051,
  "proverServerMockPort": 50052,
  "proverServerMockTimeout": 10000000,
  "proverClientPort": 50051,
  "proverClientHost": "127.0.0.1",
  "executorServerPort": 50071,
  "executorROMLineTraces": false,
  "executorClientPort": 50071,
  "executorClientHost": "127.0.0.1",
  "hashDBServerPort": 50061,
  "hashDBURL": "local",
  "aggregatorServerPort": 50081,
  "aggregatorClientPort": 50081,
  "aggregatorClientHost": "zkevm-node",
  "mapConstPolsFile": false,
  "mapConstantsTreeFile": false,
  "inputFile": "input_executor_0.json",
  "inputFile2": "input_executor_1.json",
  "keccakScriptFile": "config/scripts/keccak_script.json",
  "storageRomFile": "config/scripts/storage_sm_rom.json",
  "outputPath": "output",
  "databaseURL": "postgresql://prover_user:prover_password@merlin-state-db:5432/prover_db",
  "dbNodesTableName": "state.nodes",
  "dbProgramTableName": "state.program",
  "dbMultiWrite": true,
  "dbFlushInParallel": false,
  "dbMTCacheSize": 1024,
  "dbProgramCacheSize": 512,
  "dbNumberOfPoolConnections": 2000,
  "dbGetTree": true,
  "cleanerPollingPeriod": 600,
  "requestsPersistence": 3600,
  "maxExecutorThreads": 500,
  "maxProverThreads": 20,
  "maxHashDBThreads": 300,
  "ECRecoverPrecalc": false,
  "ECRecoverPrecalcNThreads": 4,
  "stateManager": true,
  "useAssociativeCache": false
}
  • init_prover_db.sql

    • No change.

Configuration check and migration

It's highly recommended that you compare the configuration files of the old and new versions before upgrading, and migrate any customized configurations from the old version to the new one.

During maintenance

Last batch confirmation

Execute the following command to retrieve the last batch number of your RPC node, the last batch number should be "0x#####"

curl -s -X POST --url https://rpc.merlinchain.io --header 'content-type: application/json' --data '{"id": 1, "jsonrpc": "2.0", "method": "zkevm_getBatchByNumber", "params": ["latest"]}'

Shutdown containers and backup

When the mainnet maintenance begins, stop all container services and perform the following backup actions.

  • Docker home directory and all mounted volume directories.

  • Configuration files used for initializing all local containers.

Drop database state_db

  • Start container "merlin-state-db".

  • Drop database "state_db" in container "merlin-state-db". // Do not drop "prover_db".

After maintenance

Download state_db snapshot

The state_db's snapshot will be available at the following link 1-2 hours after maintenance begins.

https://rpc-snapshot.merlinchain.io/state_db_new.sql.tar.gz

Restore state_db

Create a empty database named "state_db" with "state_user" first.

pg_restore --no-owner --no-acl --format=c --dbname=state_db --username=state_user ./state_db_new.sql.tar.gz

Drop pool_db

  • Stop and remove container "merlin-pool-db", ensure to remove your volume directory.

RPC upgrade

Using the new version of docker-compose.yml, sequentially rebuild the following containers, after stopping and deleting the containers, ensure that there are no residual files left in the corresponding mount volumes.

  • merlin-prover

  • merlin-sync

  • merlin-rpc

Last updated