Skip to content

Deploy zkNode

Continue with the fourth step of this deployment-guide where you deploy the zkNode.

zkNode deployment

First, create the following directories:

mkdir -p ~/zkevm/data/{statedb,pooldb} ~/zkevm/zkevm-config ~/zkevm/zkevm-node

Next, populate the directories by fetching data from latest node releases, for example with mainnet:

export ZKEVM_NET="mainnet"
export ZKEVM_DIR="zkevm"
curl -L https://github.com/0xPolygonHermez/zkevm-node/releases/latest/download/$ZKEVM_NET.zip > $ZKEVM_NET.zip && unzip -o $ZKEVM_NET.zip -d $ZKEVM_DIR && rm $ZKEVM_NET.zip

Copy the example.env file into .env file and open in editor:

export ZKEVM_CONFIG_DIR="/root/zkevm/zkevm-config"
cp ~/$ZKEVM_DIR/$ZKEVM_NET/example.env $ZKEVM_CONFIG_DIR/.env
vim $ZKEVM_CONFIG_DIR/.env

In the .env file, set:

ZKEVM_NODE_ETHERMAN_URL = "http://localhost:8845"  # set valid Geth Goerli RPC endpoint
ZKEVM_NODE_STATEDB_DATA_DIR = "~/zkevm/data/statedb"
ZKEVM_NODE_POOLDB_DATA_DIR = "~/zkevm/data/pooldb"

Approve MATIC token for sequencer

Run the below command to launch a Hardhat console connected to the Goerli network.

cd ~/zkevm-contracts
npx hardhat console --network goerli

Here, you can utilize the JavaScript environment to interact with the Goerli network. In the console, run the following (you can copy all the code in one go):

const provider = ethers.getDefaultProvider("http://localhost:8845"); // set Geth Goerli RPC node
const privateKey = ""; // From wallet.txt Trusted Sequencer prvkey
const wallet = new ethers.Wallet(privateKey, provider);

const maticTokenFactory = await ethers.getContractFactory(
  "ERC20PermitMock",
  provider
);
maticTokenContract = maticTokenFactory.attach(""); // From ~/zkevm-contracts/deployments/goerli_*/deploy_output.json maticTokenAddress
maticTokenContractWallet = maticTokenContract.connect(wallet);
await maticTokenContractWallet.approve("", ethers.utils.parseEther("100.0")); // From ~/zkevm-contracts/deployments/goerli_*/deploy_output.json polygonZkEVMAddress

Configure genesis

Run the below commands to copy genesis.json file into appropriate location and open for editing:

cp ~/zkevm-contracts/deployments/goerli_*/genesis.json ~/zkevm/mainnet/config/environments/testnet/public.genesis.config.json
vim ~/zkevm/mainnet/config/environments/testnet/public.genesis.config.json

Edit the file changing the following parameters from ~/zkevm/zkevm-contracts/deployments/goerli_***/deploy_output.json. Keep in mind that genesisBlockNumber is called deploymentBlockNumber in deploy_output.json.

"l1Config" : {
    "chainId": 5,
    "polygonZkEVMAddress": "", // From ~/zkevm-contracts/deployments/goerli_*/deploy_output.json polygonZkEVMAddress
    "maticTokenAddress": "", // From ~/zkevm-contracts/deployments/goerli_*/deploy_output.json maticTokenAddress
    "polygonZkEVMGlobalExitRootAddress": ""  // polygonZkEVMGlobalExitRootAddress from ~/zkevm/zkevm-contracts/deployments/goerli_*/deploy_output.json
  },
 "genesisBlockNumber": 9500870,  // deploymentBlockNumber from ~/zkevm/zkevm-contracts
# add above to head of file, leave all remaining fields intact

Update node config file

Edit ~/zkevm/mainnet/config/environments/testnet/public.node.config.toml with the following values. The config file is large and we’ll update the documentation in the future to list only the updated parameters.

Click to expand the node.config.toml file

```bash vim ~/zkevm/mainnet/config/environments/testnet/public.node.config.toml

```

```bash
IsTrustedSequencer = true
[Log]
Environment = "development"
Level = "debug"
Outputs = ["stderr","stdout"]

[StateDB]
User = "state_user"
Password = "state_password"
Name = "state_db"
Host = "zkevm-state-db"
Port = "5432"
EnableLog = false
MaxConns = 200

[Pool]
FreeClaimGasLimit = 1500000
MaxTxBytesSize=30132
MaxTxDataBytesSize=30000
DefaultMinGasPriceAllowed = 1000000000
MinAllowedGasPriceInterval = "5m"
PollMinAllowedGasPriceInterval = "15s"
    [Pool.DB]
    User = "pool_user"
    Password = "pool_password"
    Name = "pool_db"
    Host = "zkevm-pool-db"
    Port = "5432"
    EnableLog = false
    MaxConns = 200
[Etherman]
URL = "http://localhost:8845"    # put a valid Goerli node
MultiGasProvider = false
L1URL = "http://localhost:8845"  # put a valid Goerli node
L2URLs = ["http://X.X.X.X:8545"]  # your public IP
    [Etherman.Etherscan]
    ApiKey = ""     # Etherscan API key

[RPC]
Host = "0.0.0.0"
Port = 8545
ReadTimeoutInSec = 60
WriteTimeoutInSec = 60
MaxRequestsPerIPAndSecond = 5000
SequencerNodeURI = ""
BroadcastURI = "http://3.144.195.147:61090"
DefaultSenderAddress = "0x1111111111111111111111111111111111111111"
EnableL2SuggestedGasPricePolling = true
    [RPC.WebSockets]
            Enabled = true
            Port = 8546
[Synchronizer]
SyncInterval = "5s"
SyncChunkSize = 500
trustedSequencerURL = "http://X.X.X.X:8545"  # your public IP

[MTClient]
URI = "zkevm-prover:50061"

[Executor]
URI = "zkevm-prover:50071"

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

[Sequencer]
WaitPeriodPoolIsEmpty = "1s"
WaitPeriodSendSequence = "15s"
LastBatchVirtualizationTimeMaxWaitPeriod = "10s"
BlocksAmountForTxsToBeDeleted = 100
FrequencyToCheckTxsForDelete = "12h"
MaxTxsPerBatch = 150
MaxBatchBytesSize = 129848
MaxCumulativeGasUsed = 30000000
MaxKeccakHashes = 468
MaxPoseidonHashes = 279620
MaxPoseidonPaddings = 149796
MaxMemAligns = 262144
MaxArithmetics = 262144
MaxBinaries = 262144
MaxSteps = 8388608
WeightBatchBytesSize = 1
WeightCumulativeGasUsed = 1
WeightKeccakHashes = 1
WeightPoseidonHashes = 1
WeightPoseidonPaddings = 1
WeightMemAligns = 1
WeightArithmetics = 1
WeightBinaries = 1
WeightSteps = 1
TxLifetimeCheckTimeout = "10m"
MaxTxLifetime = "3h"
MaxTxSizeForL1 = 131072
    [Sequencer.Finalizer]
            GERDeadlineTimeoutInSec = "2s"
            ForcedBatchDeadlineTimeoutInSec = "60s"
            SendingToL1DeadlineTimeoutInSec = "20s"
            SleepDurationInMs = "100ms"
            ResourcePercentageToCloseBatch = 10
            GERFinalityNumberOfBlocks = 0
            ClosingSignalsManagerWaitForCheckingL1Timeout = "10s"
            ClosingSignalsManagerWaitForCheckingGER = "10s"
            ClosingSignalsManagerWaitForCheckingForcedBatches = "10s"
            ForcedBatchesFinalityNumberOfBlocks = 0
            TimestampResolution = "15s"
    [Sequencer.DBManager]
            PoolRetrievalInterval = "500ms"
    [Sequencer.Worker]
            ResourceCostMultiplier = 1000
[SequenceSender]
WaitPeriodSendSequence = "5s"
LastBatchVirtualizationTimeMaxWaitPeriod = "5s"
MaxTxSizeForL1 = 131072
SenderAddress = ""  # trustedSequencer address from deploy_output.json
PrivateKeys = [{Path = "/pk/sequencer.keystore", Password = "password"}]

[Aggregator]
Host = "0.0.0.0"
Port = 50081
ForkId = 4
RetryTime = "5s"
VerifyProofInterval = "30s"
TxProfitabilityCheckerType = "acceptall"
TxProfitabilityMinReward = "1.1"
ProofStatePollingInterval = "5s"
SenderAddress = ""  # trustedAggregator address from deploy_output.json
CleanupLockedProofsInterval = "2m"
GeneratingProofCleanupThreshold = "10m"

[EthTxManager]
ForcedGas = 0
PrivateKeys = [
    {Path = "/pk/sequencer.keystore", Password = "password"},
    {Path = "/pk/aggregator.keystore", Password = "password"}
    ]
[Database]
Database = "postgres"
User = "test_user"
Password = "test_password"
Name = "test_db"
Host = "zkevm-bridge-db"
Port = "5435"
MaxConns = 20

[BridgeController]
Store = "postgres"
Height = 32

[BridgeServer]
GRPCPort = "9090"
HTTPPort = "8080"

[NetworkConfig]
GenBlockNumber = 9500870     # deploymentBlockNumber from deploy_output.json
PolygonZkEVMAddress = ""  # polygonZkEVMAddress from deploy_output.json
PolygonBridgeAddress = ""  # PolygonZkEVMBridge from genesis.json
PolygonZkEVMGlobalExitRootAddress = ""  # polygonZkEVMGlobalExitRootAddress from deploy_output.json
MaticTokenAddress = ""  # maticTokenAddress from deploy_output.json
L2PolygonBridgeAddresses = [""]  # PolygonZkEVMBridge from genesis.json
L1ChainID = 5  # Goerli chainID

[L2GasPriceSuggester]
Type = "default"
DefaultGasPriceWei = 100000000

[ClaimTxManager]
FrequencyToMonitorTxs = "1s"
PrivateKey = {Path = "/pk/sequencer.keystore", Password = "password"}
Enabled = true
```

Add wallets

Copy/paste keystore value from wallets.txt for sequencer/aggregator respectively:

# paste only the keystore value from wallets.txt in each respective file
vim ~/zkevm/zkevm-config/sequencer.keystore
vim ~/zkevm/zkevm-config/aggregator.keystore

Last update: January 17, 2024
Authors: avenbreaks