> For the complete documentation index, see [llms.txt](https://docs.gravity.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gravity.xyz/gravity-networks/run-a-mainnet-vfn.md).

# Run a Gravity Mainnet VFN

This guide walks you through running a Validator Full Node (VFN) on Gravity Mainnet (L1, Chain ID `127001`). A VFN dials one or more validators on the VFN network and can expose a public listener for downstream PFNs.

A VFN is **not** part of the validator set and does not need validator stake. Access depends on which validator seed you connect to:

* Connecting to Gravity mainnet genesis validator seeds is currently **invite-only**. You need approved validator VFN-network seed information.
* Connecting to validators that you deploy and operate yourself does not require a Gravity mainnet invite.

> **Placeholders.** Commands below use `<YOUR_...>` placeholders. Replace each value before running. Never reuse another node's private identity or safety storage.

## Network Role

Gravity traffic flows outward from validators to VFNs, then to PFNs:

```
validators --VFN net--> VFN --public net--> PFN / RPC
```

Use a VFN when you want:

* a full node close to a validator or validator operator;
* a relay point for one or more PFNs;
* a node that follows validator-network data without joining consensus.

## Prerequisites

1. **A Linux x86-64 host**, preferably Ubuntu 24.04 LTS.
2. **`gravity_node` and `gravity_cli`.**

   ```bash
   git clone https://github.com/Galxe/gravity-sdk.git
   cd gravity-sdk
   RUSTFLAGS="--cfg tokio_unstable" \
     cargo build --profile quick-release -p gravity_node -p gravity_cli
   ```
3. **Mainnet `genesis.json` and `waypoint.txt`.** Use the canonical mainnet artifacts from [`gravity-sdk/genesis/mainnet`](https://github.com/Galxe/gravity-sdk/tree/main/genesis/mainnet); do not regenerate genesis locally.
4. **Validator VFN-network seed information.** Each validator seed needs `account_address`, host, `vfn_port`, and `network_public_key`. Genesis validator seeds require approval; self-operated validator seeds do not.
5. **SSD/NVMe storage** sized for current chain data plus growth.

## 1. Gather Validator Seed Information

For each validator you will dial, collect its public identity values from `identity.public.yaml`:

```yaml
account_address: <VALIDATOR_PEER_ID>
network_public_key: <VALIDATOR_NETWORK_PUBLIC_KEY>
```

You also need the validator host and VFN-network port, commonly `6190`.

In a standalone VFN config, prefer explicit seed entries:

```toml
seeds = [
  {
    peer_id = "<YOUR_VALIDATOR_1_ACCOUNT_ADDRESS>",
    role = "Validator",
    host = "<YOUR_VALIDATOR_1_HOST>",
    port = 6190,
    network_pk = "<YOUR_VALIDATOR_1_NETWORK_PUBLIC_KEY>"
  },
  {
    peer_id = "<YOUR_VALIDATOR_2_ACCOUNT_ADDRESS>",
    role = "Validator",
    host = "<YOUR_VALIDATOR_2_HOST>",
    port = 6190,
    network_pk = "<YOUR_VALIDATOR_2_NETWORK_PUBLIC_KEY>"
  },
]
```

Avoid `seeds = [{ from = "<id>" }]` unless the seed validator is also defined in the same TOML. The deploy script needs that validator's `host` and `vfn_port` from the same config.

## 2. Write `cluster-vfn.toml`

Download the canonical mainnet artifacts where the config below expects them:

```bash
mkdir -p <YOUR_GRAVITY_SDK_PATH>/cluster/output
curl -fsSL https://raw.githubusercontent.com/Galxe/gravity-sdk/main/genesis/mainnet/genesis.json \
  -o <YOUR_GRAVITY_SDK_PATH>/cluster/output/genesis.json
curl -fsSL https://raw.githubusercontent.com/Galxe/gravity-sdk/main/genesis/mainnet/waypoint.txt \
  -o <YOUR_GRAVITY_SDK_PATH>/cluster/output/waypoint.txt
```

Create a config such as:

```toml
[cluster]
name = "<YOUR_VFN_CLUSTER_NAME>"
base_dir = "<YOUR_DEPLOY_BASE_DIR>"

[genesis_source]
genesis_path = "./output/genesis.json"
waypoint_path = "./output/waypoint.txt"

[relayer]
relayer_rpc_url = "<YOUR_L1_RPC_URL>"

[[nodes]]
id = "vfn-1"
role = "vfn"
source = { bin_path = "../target/quick-release/gravity_node" }
identity = { source = "file" }
host = "<YOUR_VFN_HOST>"

# Deploy directory, not the database directory.
# deploy.sh renders storage to <YOUR_DEPLOY_BASE_DIR>/vfn-1/data
# and reth to <YOUR_DEPLOY_BASE_DIR>/vfn-1/data/reth.
data_dir = "<YOUR_DEPLOY_BASE_DIR>/vfn-1"

vfn_port = 6190
public_port = 6195
rpc_port = 8545
metrics_port = 9001
inspection_port = 10001
https_port = 11001
authrpc_port = 8661
reth_p2p_port = 12024
discovery_method = "none"
txpool_max_account_slots = 64

seeds = [
  {
    peer_id = "<YOUR_VALIDATOR_1_ACCOUNT_ADDRESS>",
    role = "Validator",
    host = "<YOUR_VALIDATOR_1_HOST>",
    port = 6190,
    network_pk = "<YOUR_VALIDATOR_1_NETWORK_PUBLIC_KEY>"
  },
]
```

`public_port` is optional but useful if PFNs should sync from this VFN. Keep RPC private unless you intentionally expose it behind your own gateway and access controls.

If you load identity from a secret manager, pin a fixed version rather than `latest`:

```toml
identity = {
  source = "gcp_secret",
  secret = "projects/<YOUR_PROJECT>/secrets/<YOUR_SECRET>/versions/1",
}
```

## 3. Generate Identity and Deploy

```bash
cd <YOUR_GRAVITY_SDK_PATH>/cluster
just init cluster-vfn.toml
just deploy cluster-vfn.toml
```

Expected layout:

```
<YOUR_DEPLOY_BASE_DIR>/vfn-1/config/
<YOUR_DEPLOY_BASE_DIR>/vfn-1/data/
<YOUR_DEPLOY_BASE_DIR>/vfn-1/script/start.sh
<YOUR_DEPLOY_BASE_DIR>/vfn-1/script/stop.sh
```

The public identity generated for the VFN is written to:

```
<YOUR_GRAVITY_SDK_PATH>/cluster/output/vfn-1/config/identity.public.yaml
```

If downstream PFNs will use this VFN as a seed, share the VFN sidecar `account_address`, `network_public_key`, host, and `public_port`.

## 4. Optional: Warm Start From an Existing Node

To speed up initial sync, copy only chain databases from an existing RPC/PFN or VFN you control:

```bash
cd <YOUR_EXISTING_NODE_DATA_DIR>
tar -cf - consensus_db quorumstoreDB reth | \
  ssh <YOUR_TARGET_HOST> \
    "mkdir -p <YOUR_DEPLOY_BASE_DIR>/vfn-1/data && \
     cd <YOUR_DEPLOY_BASE_DIR>/vfn-1/data && tar -xf -"
```

Do **not** copy `rand_db` or `secure_storage.json` from another node. `secure_storage.json` contains node-specific safety state and can make the node behave as if it belongs to a different identity.

## 5. Start and Verify

```bash
bash <YOUR_DEPLOY_BASE_DIR>/vfn-1/script/start.sh
```

Check logs:

```bash
tail -n 200 <YOUR_DEPLOY_BASE_DIR>/vfn-1/consensus_log/vfn.log
ls -lh <YOUR_DEPLOY_BASE_DIR>/vfn-1/execution_logs
```

Check RPC height:

```bash
curl -s http://127.0.0.1:8545 \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
```

Compare with the public head:

```bash
curl -s https://mainnet-rpc.gravity.xyz \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
```

## Troubleshooting

| Symptom                                                      | Cause / fix                                                                                                    |
| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `seeds: from=<id>: missing host or vfn_port in cluster.toml` | Use explicit seed entries, or define the seed validator in the same TOML.                                      |
| VFN does not advance                                         | Verify validator seed `peer_id`, host, `vfn_port`, and `network_public_key`; also verify genesis and waypoint. |
| Downstream PFNs cannot connect                               | Confirm `public_port` is open, reachable, and advertised with the VFN `network_public_key`.                    |
| Paths render as `<node>/data/<node>`                         | `data_dir` should be the node deploy directory, not the final database directory.                              |
| Identity-related errors after copying data                   | Remove any copied `secure_storage.json`; it must not be reused across nodes.                                   |

## See Also

* [Run a Gravity Mainnet Public Full Node](/gravity-networks/run-a-mainnet-pfn.md)
* [Run a Gravity Mainnet Validator](/gravity-networks/run-a-mainnet-validator.md)
* [Gravity Mainnet (L1)](/gravity-networks/l1-mainnet.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.gravity.xyz/gravity-networks/run-a-mainnet-vfn.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
