# Benchmark Reproduction Guide

### Overview

* **Goal**: Continuously stress Gravity's RPC endpoints and measure throughput (TPS) and latency.
* **Repository**: `https://github.com/Galxe/gravity_bench`
* **What the tool does**:
  * Deploys the required ERC20 contracts.
  * Prepares a large pool of accounts/addresses.
  * Concurrently sends transactions to one or more RPC endpoints.

### Prerequisites

1. **A `gravity_node` binary built in release mode** — benchmark results are only meaningful when the node is compiled with optimizations. Refer to [gravity-sdk/readme.md](https://github.com/Galxe/gravity-sdk/blob/main/readme.md) for full build instructions. The recommended command is:

   ```bash
   make BINARY=gravity_node MODE=quick-release
   ```
2. **A running Gravity EVM cluster** (refer to: [Validator Cluster Deployment Guide](/developer-resources/cluster-deployment.md)):
   * Code release: <https://github.com/Galxe/gravity-sdk/releases/tag/gravity-testnet-v1.0.0>
     * Note: example cluster configurations are available at: <https://github.com/Galxe/gravity-sdk/tree/main/cluster/example>
   * `chain_id`: `1337 (example)`
   * `nodes1`: `http://127.0.0.1:8545 (example Validator1)`
   * `nodes2`: `http://127.0.0.1:8546 (example Validator2)`
   * `nodes3`: `http://127.0.0.1:8547 (example Validator3)`
3. **A funded EOA** for use as **faucet + deployer**:

   * You must provide this account's private key in the config file.
   * The account needs sufficient native token balance to:
     * Fund a large number of test accounts (directly or via cascading faucet mode).
     * Pay gas for contract deployment.

   A test faucet account is pre-funded in genesis.toml, with private key\
   `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80`,\
   corresponding to address `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`.\
   The following configuration must be present in genesis.toml to give this address a balance:

   ```toml
   [genesis.faucet]
   address = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
   private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
   balance = "1000000000000000000000000"   # 1M ETH
   ```

### System Dependencies (Ubuntu)

Install all required build and runtime packages in one step:

```bash
sudo apt update && sudo apt install -y \
  build-essential clang pkg-config libssl-dev git curl \
  libudev-dev libusb-1.0-0-dev \
  python3 python-is-python3 python3-pip python3-venv \
  nodejs npm
```

> `python-is-python3` creates the `python` command alias required by gravity\_bench's internal scripts. `libudev-dev` / `libusb-1.0-0-dev` prevent common build errors when compiling `hidapi`.

### Environment Setup

1. **Clone the repository**

   ```bash
   git clone https://github.com/Galxe/gravity_bench.git
   cd gravity_bench
   ```
2. **Run the initialization script**

The script will:

* Check and install missing tools (Rust, Node.js, Python)
* Create a Python virtual environment
* Install Python and Node dependencies
* Clone the contract repositories required for benchmarking

**Recommended (keep the environment active in the current shell):**

```bash
source setup.sh
```

> ⚠️ On Ubuntu, if you see `Failed to create Python virtual environment`, first run:
>
> ```bash
> sudo apt install python3-venv
> ```
>
> Then re-run `source setup.sh`.

**Alternative (requires manual environment activation):**

```bash
bash setup.sh
# Then manually activate the environment:
source venv/bin/activate
source ~/.cargo/env  # only needed if the script installed Rust
```

### Configuration

1. **Create a local config file**

   ```bash
   cp bench_config.template bench_config.toml
   ```
2. **Edit `bench_config.toml`**

Key fields to review:

* `nodes`: one or more RPC endpoints
* `target_tps`: target benchmark TPS; recommended not to exceed 9k on a 3-node cluster
* `[faucet].private_key`: **private key of the funded faucet/deployer account**
* `[accounts].num_accounts`: number of benchmark accounts; 100k recommended
* `[performance]`: concurrency and pool configuration

**Configuration constraints** — violating these will cause an assertion failure on startup:

* `accounts.num_accounts` ≥ `target_tps`
* `performance.num_senders` ≤ `accounts.num_accounts`

Example (abbreviated):

```toml
# Gravity Bench Configuration File

# Uniswap configuration file path (generated by deployment)
contract_config_path = "deploy.json"

# Target sending rate
target_tps = 9000

# RPC endpoints, replace with your chain_id and addresses
nodes = [
    { rpc_url = "http://127.0.0.1:8545", chain_id = 1337 },
    { rpc_url = "http://127.0.0.1:8546", chain_id = 1337 },
    { rpc_url = "http://127.0.0.1:8547", chain_id = 1337 },
]

num_tokens = 1
enable_swap_token = false

# Address pool type: "random" (default) or "weighted" (hot/normal/long-tail distribution)
address_pool_type = "random"

[faucet]
# Private key (replace with your real key)
private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"

# Faucet Level:
# - 10 enables cascade mode: 1 -> 10 -> 100 (amplification chain)
# - 0 disables cascading
faucet_level = 10

# Wait between faucet distribution levels (increase if you see insufficient funds)
wait_duration_secs = 1

# Target ETH balance per funded account (in wei)
fauce_eth_balance = "1000000000000000000000"

[accounts]
num_accounts = 100000

[performance]
# Number of concurrent transaction sending tasks inside TxnConsumer
num_senders = 600

# Max in-memory pool size inside the consumer
max_pool_size = 100000

# Benchmark duration in seconds (0 = run indefinitely)
duration_secs = 0

# Sampling strategy: integer = sample every N txns, or "full" to check all pending
sampling = 20
```

### Running the Benchmark

#### First Run (includes faucet distribution + contract deployment)

For the first run (or when you want to re-initialize accounts/contracts):

```bash
cargo run --release -- --config bench_config.toml
```

This step will:

* Distribute funds to test accounts using the faucet private key.
* Deploy the required contracts.
* Generate (or update) `deploy.json`, referenced by `contract_config_path`.

#### Subsequent Runs (reuse existing state)

Once contracts are deployed and `deploy.json` exists, use recovery mode:

```bash
cargo run --release -- --config bench_config.toml --recover
```

### Diagnostics

**Verify an RPC endpoint is reachable and get its `chain_id`:**

```bash
curl -s http://127.0.0.1:8545 \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
# expect 0x539 for chainId 1337
```

**Check a faucet account balance:**

```bash
curl -s http://127.0.0.1:8545 \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266","latest"]}'
```

### Troubleshooting

| Symptom                                                       | Fix                                                                                                                    |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Build error: `libudev.pc` / `hidapi` / `pkg-config` not found | `sudo apt install -y libudev-dev libusb-1.0-0-dev pkg-config`                                                          |
| `python: command not found`                                   | `sudo apt install -y python-is-python3`                                                                                |
| `ModuleNotFoundError: No module named 'web3'`                 | Ensure you're in the `gravity_bench` directory and run `source setup.sh` again                                         |
| `SolcError` or missing Uniswap/OpenZeppelin contracts         | Remove `contracts/` and `node_modules/` then re-run `source setup.sh`                                                  |
| `insufficient funds for gas * price + value`                  | Increase `faucet.wait_duration_secs` in `bench_config.toml`; for a local cluster, restart all nodes to reset state     |
| `assertion failed: accounts.num_accounts >= target_tps`       | Increase `accounts.num_accounts` to be ≥ `target_tps`                                                                  |
| `Connection refused` / wrong network                          | Verify `rpc_url` is correct and the cluster is running; confirm `chain_id` matches the value returned by `eth_chainId` |

### Visualization

For Grafana / Prometheus deployment and dashboard import, refer to:

* Grafana / Prometheus deployment guide coming soon.


---

# Agent Instructions: 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:

```
GET https://docs.gravity.xyz/developer-resources/benchmark-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
