> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/ecosystem/nodes/cpp/run-validator",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Run a validator

> Run a validator node with MyTonCtrl

export const Image = ({src, darkSrc, alt = '', darkAlt, href, target, height = 342, width = 608, noZoom = false, center = false}) => {
  const isSVG = src.match(/\.svg(?:[#?].*?)?$/i) !== null;
  const shouldInvert = isSVG && !darkSrc;
  const shouldCreateLink = href !== undefined;
  const minPx = 9;
  const maxPx = 608;
  const expectedPx = `a number or a string with a number that is greater than ${minPx - 1} and less than or equal to ${maxPx}`;
  const createInvalidPropCallout = (title, received, expected) => {
    return <Danger>
        <span className="font-bold">
          Invalid <code>{title.toString()}</code> passed!
        </span>
        <br />
        <span className="font-bold">Received: </span>
        {received.toString()}
        <br />
        <span className="font-bold">Expected: </span>
        {expected.toString()}
        {}
      </Danger>;
  };
  const checkValidDimensionValue = value => {
    switch (typeof value) {
      case "string":
      case "number":
        const num = Number(value);
        return Number.isSafeInteger(num) && num >= minPx && num <= maxPx;
      default:
        return false;
    }
  };
  let callouts = [];
  if (height && !checkValidDimensionValue(height)) {
    callouts.push(createInvalidPropCallout("height", height, expectedPx));
  }
  if (width && !checkValidDimensionValue(width)) {
    callouts.push(createInvalidPropCallout("width", width, expectedPx));
  }
  if (callouts.length !== 0) {
    return callouts;
  }
  const heightPx = Number(height);
  const widthPx = Number(width);
  const shouldCenter = center === "true" || center === true ? true : false;
  const shouldNotZoom = noZoom === "true" || noZoom === true ? true : false;
  const images = <>
      <img className="block dark:hidden" src={src} alt={alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
      <img className={`hidden dark:block ${shouldInvert ? "invert" : ""}`} src={darkSrc ?? src} alt={darkAlt ?? alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
    </>;
  if (shouldCreateLink) {
    if (shouldCenter) {
      return <div style={{
        display: "flex",
        justifyContent: "center"
      }}>
          <a href={href} target={target ?? "_self"}>
            {images}
          </a>
        </div>;
    }
    return <a href={href} target={target ?? "_self"}>
        {images}
      </a>;
  }
  if (shouldCenter) {
    return <div style={{
      display: "flex",
      justifyContent: "center"
    }}>{images}</div>;
  }
  return images;
};

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

## Overview

This guide explains how to run a validator TON node with MyTonCtrl from scratch.

<Image src="/resources/images/nodes/run-validator/run-validator-30.png" darkSrc="/resources/images/nodes/run-validator/run-validator-30.png" alt="Architecture" />

## Step 1: Prepare environment

### 1.1 Maintain costs and expenses

* 200 TON per month on the validator hot wallet for its operational transactions.
* Validator deposit stake [700 000 TON \~ 4 000 000 TON](/ecosystem/nodes/cpp/run-validator#step-4:-set-optimal-stake-for-validator).
* 100 TB/month traffic at a peak load.

### 1.2 Minimal hardware requirements

* 16-core CPU (for example, Intel Xeon E-2388G or equivalent)
* 128 GB RAM
* 2 × 1.92 TB NVMe SSD, each with 250,000+ read IOPS and 83,000+ write IOPS
* 1 Gbit/s network connectivity
* Fixed (static) public IP address

<Aside type="tip">
  A 1 Gbit/s network connection is recommended to ensure reliable performance during peak load conditions. The average expected bandwidth usage is approximately 100 Mbit/s.

  Validators must carefully consider IOPS disk requirements, as insufficient storage performance can severely impact validator stability and overall network health. Prefer faster NVMe drives — validator performance depends heavily on disk speed.
</Aside>

### 1.3 Software requirements

* Ubuntu 22.04 LTS or 24.04 LTS
* Python 3.10 or higher
* Clang 16.0.0 or higher

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
# Check Ubuntu version
cat /etc/os-release
```

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
# Check Python version
python3 --version
```

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
# Check Clang version
clang --version
```

<Image src="/resources/images/nodes/run-validator/run-validator-3.png" darkSrc="/resources/images/nodes/run-validator/run-validator-3.png" alt="Versions output" />

<Accordion title="Update Clang...">
  ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  # Check Clang version
  clang --version
  # If version 16, skip the steps below.

  # Required for Ubuntu 22.04. Update current Clang to clang-16
  sudo apt update
  sudo apt install -y lsb-release wget software-properties-common gnupg
  sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
  wget https://apt.llvm.org/llvm.sh
  chmod +x llvm.sh
  sudo ./llvm.sh 16 clang

  # Change default Clang
  sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100
  sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100

  # Required for Ubuntu 24.04. Install clang-16
  sudo apt install -y clang-16

  ```
</Accordion>

### 1.4 Port forwarding for validator

Configure the network on the server according to the following:

* All outgoing connections are allowed.
* A static external IP address.
* [One UDP port open for incoming connections.](/ecosystem/nodes/cpp/run-validator#2-4-verify-validator’s-port)

### 1.5 Follow network announcements

Subscribe and follow the instructions provided for validators with Telegram channels.

<Aside type="tip">
  Do not ignore announcements for TON Testnet; validators that violate the maintenance rules are fined and excluded from the network.
</Aside>

| Channel                                      | Network     |
| -------------------------------------------- | ----------- |
| [@tonstatus](https://t.me/tonstatus)         | TON Mainnet |
| [@testnetstatus](https://t.me/testnetstatus) | TON Testnet |

### 1.6 Prepare validator user

Prepare and log in a user for the validator.

1. Create a non-root user

   ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
   # Create a non-root validator user
   sudo adduser <USERNAME>
   sudo usermod -aG sudo <USERNAME>
   ```

2. Switch to it by reconnecting to the server via `ssh`

   ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
   #reconnect as the new user
   exit
   ssh <USERNAME>@<SERVER_IP>
   ```

### 1.7 Benchmark server performance

Before installing, verify that the server meets performance requirements. Inadequate disk or network performance is the most common cause of validator instability.

#### Network latency

Check latency to TON beacon nodes. Expect approximately 50 milliseconds to the nearest beacon and up to 300 milliseconds to the farthest:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
ping beacon-eu-01.toncenter.com -c 6
ping beacon-apac-01.toncenter.com -c 6
```

#### Disk IOPS

Install `fio` and run a random read/write benchmark:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo apt install -y fio
fio --randrepeat=1 --ioengine=libaio --max-jobs=16 --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=10G --filename=/tmp/bench
rm /tmp/bench
```

Run the benchmark on the same disk where validator data will be stored (`/var/ton-work/`). If `/tmp` is on a different filesystem, replace `/tmp/bench` with a path on the target drive.

Minimum acceptable results:

| Metric | Minimum             |
| ------ | ------------------- |
| Read   | 250k IOPS, 981 MB/s |
| Write  | 83k IOPS, 327 MB/s  |

<Aside type="caution">
  If disk performance is below these thresholds, the validator may fail to keep up with the network. Upgrade storage before proceeding.
</Aside>

#### Network bandwidth

Verify network throughput with `speedtest-cli`:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo apt install -y speedtest-cli
speedtest-cli
```

Ensure download and upload speeds meet the [1 Gbit/s requirement](/ecosystem/nodes/cpp/run-validator#1-2-minimal-hardware-requirements).

### 1.8 Harden server security

<Aside type="caution" title="Security baseline">
  A compromised validator server puts staked funds at risk. Apply these hardening steps before exposing the server to the network.
</Aside>

#### SSH hardening

Apply the following SSH configuration changes in `/etc/ssh/sshd_config`:

* Enable key-based authentication and disable password login:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
PasswordAuthentication no
PubkeyAuthentication yes
```

* Disable root login:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
PermitRootLogin no
```

* Change the default SSH port:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
Port <SSH_PORT>
```

`<SSH_PORT>` — a non-default port number (for example, `2222`).

* Restrict SSH access to specific IP addresses using the `Match Address` directive:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
Match Address <ALLOWED_IP>
  AllowUsers <USERNAME>
```

Restart the SSH service after changes:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo systemctl restart sshd
```

#### Firewall configuration

Enable the firewall and allow only the SSH port. The validator UDP port is added after installation in [step 2.5](/ecosystem/nodes/cpp/run-validator#2-5-check-validator's-port).

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo ufw allow <SSH_PORT>/tcp
sudo ufw enable
sudo ufw status
```

#### Additional security measures

* Use a unique, strong password for the root user.

* Set a GRUB bootloader password to prevent unauthorized boot modifications.

* Enable Fail2ban for SSH brute-force protection:

  ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  sudo apt install -y fail2ban
  sudo systemctl enable fail2ban
  sudo systemctl start fail2ban
  ```

* Configure two-factor authentication for SSH using `libpam-google-authenticator` or a similar PAM module.

#### Encrypt sensitive directories (optional)

For additional protection, store validator keys and configuration on an encrypted partition. Create an encrypted volume and symlink the [backup directories](/ecosystem/nodes/cpp/run-validator#5-5-organize-validator-backup) from it.

<Aside type="tip">
  After moving directories to the encrypted partition, create symlinks in their original locations so that MyTonCtrl and the validator service continue to function without path changes.
</Aside>

## Step 2: Validator node installation

### 2.1 Download validator installer (MyTonCtrl)

Run:

```shell theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
```

<Image src="/resources/images/nodes/run-validator/run-validator-4.png" darkSrc="/resources/images/nodes/run-validator/run-validator-4.png" alt="Downloading MyTonCtrl" />

### 2.2 Run validator installation

Run the validator installation. Installation takes approximately 20 minutes:

<CodeGroup>
  ```shell Mainnet theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  sudo bash install.sh -m single-nominator -n mainnet
  ```

  ```shell Testnet theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  sudo bash install.sh -m single-nominator -n testnet
  ```
</CodeGroup>

<Image src="/resources/images/nodes/run-validator/run-validator-5.png" darkSrc="/resources/images/nodes/run-validator/run-validator-5.png" alt="Expected final output for validator installation" />

<Accordion title="Speed up initial sync with a database dump...">
  To reduce synchronization time from hours to minutes, download a pre-built database dump instead of syncing from peers. Check the [dump index](https://dump.ton.org/) for available snapshots.

  1. Install `aria2` and `plzip` if not already present:

     ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
     sudo apt install -y aria2 plzip
     ```

  2. Stop the validator and MyTonCore services:

     ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
     sudo systemctl stop mytoncore.service
     sudo systemctl stop validator.service
     ```

  3. Download and extract the dump:

     ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
     cd /var/ton-work/
     aria2c -x 16 https://dump.ton.org/dumps/latest.tar.lz
     mv /var/ton-work/db /var/ton-work/db_old
     mkdir /var/ton-work/db
     plzip -d -c /var/ton-work/latest.tar.lz | tar -xvf - -C /var/ton-work/db
     ```

  4. Restore configuration and keys from the original database:

     ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
     cp /var/ton-work/db_old/config.json /var/ton-work/db/config.json
     cp -r /var/ton-work/db_old/keyring /var/ton-work/db/keyring
     sudo chown -R validator:validator /var/ton-work/db
     ```
</Accordion>

### 2.3 Verify status results

Launch MyTonCtrl with the command `mytonctrl`. Then, check synchronization using the `status` command:

```sh theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
mytonctrl
MyTonCtrl> status
```

Verify that the correct modes are enabled:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> status_modes
```

Expected output should show `validator` and `single-nominator` as enabled, with all other modes disabled.

<Image src="/resources/images/nodes/run-validator/run-validator-2.png" darkSrc="/resources/images/nodes/run-validator/run-validator-2.png" alt="MyTonCtrl status results" />

<Aside type="tip">
  Initially, the status shows "Local validator initial sync status: downloading blockchain state x", which indicates that the node has started synchronization.
  There are also other status messages in the very beginning of the synchronization, such as "starting", "init block seqno", "last key block is x", "downloading all shard states", "mc seqno" - all these statuses are fine.
</Aside>

### 2.4 Verify validator's port

Print `engine.addr` port configuration `config.json` file:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
grep -A5 '"addrs"' -n /var/ton-work/db/config.json | grep '"port"' | head -1
```

<Image src="/resources/images/nodes/run-validator/run-validator-26.png" darkSrc="/resources/images/nodes/run-validator/run-validator-26.png" alt="Print validator port" />

### 2.5 Check validator's port

Make sure UDP `engine.addr` port is allowed with the following command:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo ufw status
```

<Image src="/resources/images/nodes/run-validator/run-validator-25.png" darkSrc="/resources/images/nodes/run-validator/run-validator-25.png" alt="Check allowed ports" />

If the port is filtered (absent in allowed), open this port:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
sudo ufw allow <PORT_NUMBER>/udp
```

Then make sure with `sudo ufw status`.

### 2.6 Verify node synchronization

Wait until the node is fully synchronized, which takes approximately 3 hours (depending on the network connection). Check the field `Local validator initial sync status: x`, the value x should become less than 20.

<Image src="/resources/images/nodes/run-validator/run-validator-8.png" darkSrc="/resources/images/nodes/run-validator/run-validator-8.png" alt="Verify node synchronization in status" />

<Aside type="tip">
  Set up [alert bot](/ecosystem/nodes/cpp/integrating-with-prometheus) to receive a notification when the node is synchronized.
</Aside>

## Step 3: Configure validator

When installing, MyTonCtrl automatically creates a validator wallet. Top up and activate (deploy) this wallet so MyTonCtrl can operate the single nominator pool smart contract with it.

### 3.1 Get validator wallet address

```sh theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> wl
```

Find the wallet named `validator_wallet_001` and its address.

<Image src="/resources/images/nodes/run-validator/run-validator-7.png" darkSrc="/resources/images/nodes/run-validator/run-validator-7.png" alt="Print validator wallet list" />

### 3.2 Back-up validator wallet secret key

<Aside type="caution">
  This private key is required to restore access to the funds stored in the validator wallet. It is not involved in managing rewards or staking.
</Aside>

Make a backup of the validator wallet secret key:

```sh theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> ew validator_wallet_001
```

<Image src="/resources/images/nodes/run-validator/run-validator-11.png" darkSrc="/resources/images/nodes/run-validator/run-validator-11.png" alt="Back-up validator wallet" />

<Aside type="tip">
  Import this secret key with [`iw`](/ecosystem/nodes/cpp/mytonctrl/wallet#iw) command.
</Aside>

### 3.3 Explore validator wallet

Explore validator wallet by address with [Tonviewer](https://tonviewer.com/):

<Image src="/resources/images/nodes/run-validator/run-validator-6.png" darkSrc="/resources/images/nodes/run-validator/run-validator-6.png" alt="Explore validator wallet" />

### 3.4 Credit validator wallet

<Aside type="danger" title="Funds at risk">
  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`. Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.
</Aside>

Credit the validator wallet. Ensure that at least 200 TON per month is available in the validator’s wallet to cover operational fees.

<Image src="/resources/images/nodes/run-validator/run-validator-9.png" darkSrc="/resources/images/nodes/run-validator/run-validator-9.png" alt="Credit validator wallet" />

### 3.5 Activate the wallet

Activate (deploy on-chain) validator wallet, run:

```sh theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> aw validator_wallet_001
```

<Image src="/resources/images/nodes/run-validator/run-validator-12.png" darkSrc="/resources/images/nodes/run-validator/run-validator-12.png" alt="Activate validator wallet command result" />

That also reflects in Tonviewer; the status will be displayed as `Active`

<Image src="/resources/images/nodes/run-validator/run-validator-14.png" darkSrc="/resources/images/nodes/run-validator/run-validator-14.png" alt="Validator wallet in explorer" />

### 3.6 Create a pool

Create a [single nominator pool](https://docs.ton.org/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool) for secure stake management. As the `owner-address`, specify the beneficiary wallet address that will stake the owner's funds and receive rewards.

<Aside type="danger" title="Funds at risk">
  Use a cold wallet (e.g., Ledger) for the `owner-address` and store its seed phrase securely to keep funds safe. If access to the owner's wallet is lost, access to stake and rewards funds cannot be recovered.
</Aside>

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> new_single_pool <pool-name> <owner-address>
```

<Image src="/resources/images/nodes/run-validator/run-validator-15.png" darkSrc="/resources/images/nodes/run-validator/run-validator-15.png" alt="Create a single pool" />

<Accordion title="If a single nominator pool already exists...">
  If a single-nominator pool is already created, import it with:

  ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  MyTonCtrl> import_pool <pool-name> <pool-addr>
  ```
</Accordion>

### 3.7 Print pool list

Explore pool addresses using `pools_list` command:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> pools_list
```

<Image src="/resources/images/nodes/run-validator/run-validator-16.png" darkSrc="/resources/images/nodes/run-validator/run-validator-16.png" alt="Pool list result" />

At the moment, the pool hasn't been deployed yet, and Explorer will display this as `Nonexist` status

<Image src="/resources/images/nodes/run-validator/run-validator-17.png" darkSrc="/resources/images/nodes/run-validator/run-validator-17.png" alt="Nonexist pool" />

### 3.8 Activate pool

Activate the single pool nominator contract:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> activate_single_pool <pool-name>
```

<Image src="/resources/images/nodes/run-validator/run-validator-18.png" darkSrc="/resources/images/nodes/run-validator/run-validator-18.png" alt="Activate the pool result" />

### 3.9 Verify activated pool

Make sure the pool becomes activated with `pools_list`:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> pools_list
```

<Image src="/resources/images/nodes/run-validator/run-validator-19.png" darkSrc="/resources/images/nodes/run-validator/run-validator-19.png" alt="Pool list" />

[Blockchain explorer](/ecosystem/explorers/overview) should also display the now-deployed contract with `Active` status.

<Image src="/resources/images/nodes/run-validator/run-validator-20.png" darkSrc="/resources/images/nodes/run-validator/run-validator-20.png" alt="Find pool in explorer" />

<Aside type="caution">
  After activation, verify the following in a [blockchain explorer](/ecosystem/explorers/overview):

  1. The pool contract code hash matches the [official single nominator pool contract](https://github.com/orbs-network/single-nominator/blob/main/README.md).
  2. The owner address stored in the pool matches the address specified during creation.

  Skipping these checks may result in funds being sent to an incorrect or malicious contract.
</Aside>

### 3.10 Test deposit to pool

<Aside type="danger" title="Funds at risk">
  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`. Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.
</Aside>

Test deposit to stake workflow. Any user can deposit to the pool via a standard direct TON transfer.
Credit decent sum around 10 TON:

<Image src="/resources/images/nodes/run-validator/run-validator-21.png" darkSrc="/resources/images/nodes/run-validator/run-validator-21.png" alt="Test deposit 1" />

<Image src="/resources/images/nodes/run-validator/run-validator-22.png" darkSrc="/resources/images/nodes/run-validator/run-validator-22.png" alt="Test deposit 2" />

### 3.11 Test withdrawal from pool

Test withdrawal workflow. Only the [owner's cold wallet](/ecosystem/nodes/cpp/run-validator#3-6-create-a-pool) can request a withdrawal.
Send a withdrawal request, a message with `w` comment from `owner` wallet to the single nominator pool address:

<Image src="/resources/images/nodes/run-validator/run-validator-24.jpg" width="280" darkSrc="/resources/images/nodes/run-validator/run-validator-24.jpg" alt="Send withdrawal request" />

<Accordion title="Withdraw with script...">
  Insert the single nominator pool address to `SINGLE_NOMINATOR_ADDRESS` and send this message from the owner's wallet.

  ```js Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  import {
    Address,
    beginCell,
    internal,
    storeMessageRelaxed,
    toNano,
  } from "@ton/core";

  async function main() {
    const single_nominator_address = Address.parse("SINGLE_NOMINATOR_ADDRESS");
    const WITHDRAW_OP = 0x1000;
    const amount = 50000;

    const messageBody = beginCell()
      .storeUint(WITHDRAW_OP, 32)
      .storeUint(0, 64)
      .storeCoins(amount)
      .endCell();

    const internalMessage = internal({
      to: single_nominator_address,
      value: toNano("1"),
      bounce: true,
      body: messageBody,
    });
  }

  ```
</Accordion>

Once the deposit is restored (except 1 TON reserve on the single nominator pool) to the owner's wallet, that means validator are set securely and ready for real stake:

<Image src="/resources/images/nodes/run-validator/run-validator-23.png" darkSrc="/resources/images/nodes/run-validator/run-validator-23.png" alt="Pool list" />

## Step 4: Set optimal stake for validator

Top up the single nominator pool with the effective validation stake. In the next elections, MyTonCtrl will automatically use this pool for staking. Aim for a stake that places the validator between positions 200 and 250 in the [validator index](https://tonscan.org/validators).

<Aside type="tip">
  If the pool's balance is sufficient to participate in both rounds `balance > min_stake_amount * 2`, MyTonCtrl will automatically participate in both rounds using `stake = balance / 2`, unless the stake is manually set using the `set stake` command. This behavior differs from using a nominator pool but resembles staking with a validator wallet.
</Aside>

### 4.1 Retrieve stakes for last two cycles

Check the current validator stakes on [tonscan.org/validators](https://tonscan.org/validators) and the minimum network stake in the [network config](https://tonviewer.com/config).

Retrieve `min_stake` and `max_stake` from [Validation API](https://elections.toncenter.com/getValidationCycles?return_participants=false\&offset=0\&limit=2) for two last cycles.

<Accordion title="See expected result...">
  <Image src="/resources/images/nodes/run-validator/run-validator-28.png" darkSrc="/resources/images/nodes/run-validator/run-validator-28.png" alt="Cycle info API response" />
</Accordion>

For example:

```json Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
"cycle_id" : 1764052744,
"min_stake": 701812111528562,  // ~ 701 812 TON
"max_stake": 2008570202020000, // ~ 2 008 570 TON
```

```json Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
"cycle_id" : 1764052744,
"min_stake": 674810775114391,  // ~ 674 811 TON
"max_stake": 2024432325343173, // ~ 2 024 432 TON
```

<Aside type="tip">
  Values retrieved in nanotons, divide this by $10^9$ to get TON units.
</Aside>

### 4.2 Retrieve stakes boundary values

To cover the approximate expected stake for odd and even cycles, choose the maximum between the two `min_stake` and the maximum between the two `max_stake`.

For example:

```text Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
// largest within 701 812 TON and 674 811 TON
avg_min_stake = 701812

// largest within 2 008 570 TON and 2 024 432 TON
avg_max_stake = 2024432
```

### 4.3 Calculate effective stakes

<Aside type="tip">
  *Effective* stands for winning elections for both odd and even cycles.
</Aside>

Effective stake for two cycles is a value between the doubled maximum and the minimum average stakes:

```text Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
avg_min_stake * 2 <= effective_stake <= avg_max_stake * 2
```

For example:

```text Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
// twice the average minimum stake
min_expected_effective_stake = 1403624

// twice the average maximum stake
max_expected_effective_stake = 4048864
```

Then, the effective stake is approximately:

```text Not runnable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
1403624 TON <= effective_stake <= 4048864 TON
```

### 4.4 Deposit effective stake

<Aside type="danger" title="Funds at risk">
  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`.
  Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.
</Aside>

Deposit effective stake to the single nominator pool address.

### 4.5 Track first cycle progress

In the next election cycle (odd/even), MyTonCtrl will send half of the stake from the single nominator pool. Track this with a [blockchain explorer](/ecosystem/explorers/overview).

### 4.6 Track second cycle progress

In the next paired election cycle (even/odd), MyTonCtrl will send the second half of the stake from the single nominator pool. Track this with a [blockchain explorer](/ecosystem/explorers/overview).

### 4.7 Verify entire staking cycle

The reward for the odd validation cycle will be returned to the single nominator pool, combined with the stake. Verify this with a blockchain explorer. A few minutes after the reward is accepted, MyTonCtrl initiates a re-stake of this stake, including the reward.

<Image src="/resources/images/nodes/run-validator/run-validator-29.png" darkSrc="/resources/images/nodes/run-validator/run-validator-29.png" alt="One cycle staking history" />

**Legend**

1. Stake for odd cycle.
2. Reward for odd cycle.
3. Reinvestment of the odd cycle stake, including the reward in the next odd cycle.

### 4.8 Switch to daily maintenance

Make sure pair stakes are appropriately circulated, then focus on monitoring validator health and updates.

## Step 5: Maintain validator

### 5.1 Fund the validator hot wallet

Keep at least 200 TON on the validator hot wallet. This balance covers operational fees for approximately one month.

To check the current balance:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> wl
```

### 5.2 Top up the single nominator pool

Before sending funds to the pool:

* Verify that the pool address is correct and uses the **bounceable** format.
* Confirm that the pool smart contract is still active and not frozen. A pool can become frozen if the entire balance is consumed by storage fees between creation and funding.
* Follow the [test deposit and withdrawal procedure](/ecosystem/nodes/cpp/run-validator#3-10-test-deposit-to-pool) before depositing the full stake.

<Aside type="tip">
  By default, MyTonCtrl splits the pool balance 50/50 between odd and even validation cycles. Ensure the total stake is sufficient to participate in both cycles: `balance > min_stake * 2`.
</Aside>

If the pool does not pick up the deposit automatically, push it manually:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> mg validator_wallet_001 <POOL_ADDRESS> 5
```

`<POOL_ADDRESS>` — the bounceable address of the single nominator pool.

### 5.3 Withdraw funds from the pool

Only the owner wallet can withdraw funds. Follow the [test withdrawal procedure](/ecosystem/nodes/cpp/run-validator#3-11-test-withdrawal-from-pool) using the same method.

### 5.4 Follow the TON announcements channel

Follow the [@tonstatus](https://t.me/tonstatus) channel, turn on notifications, and be prepared for urgent updates if needed.

### 5.5 Organize validator backup

Back up the following paths to an encrypted, off-site location:

* `/var/ton-work/db/config.json`
* `/var/ton-work/db/keyring`
* `/var/ton-work/keys`
* `/usr/local/bin/mytoncore` (includes wallet files such as `validator_wallet_001.pk` and `validator_wallet_001.addr`)

<Aside type="danger">
  Store backups in an encrypted format in a secure location. Loss of these files means loss of access to the validator and staked funds.
</Aside>

Alternatively, use the built-in MyTonCtrl backup:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> create_backup
```

### 5.6 Set up alerting

Set up alerting in MyTonCtrl to get a notification of critical issues with the validator. For more information, see [MyTonCtrl private alerting bot](/ecosystem/nodes/cpp/mytonctrl/alerting) or check [MyTonCtrl public alerting bot](https://t.me/validators).

### 5.7 Set up monitoring

Set up monitoring dashboards for RAM, disk, network, CPU usage, and other metrics.

* For on-chain validator metrics, use the [`ton-validators-metrics` system](https://github.com/the-ton-tech/ton-validators-metrics).
* For system-level metrics, [integrate Prometheus with `node_exporter` with MyTonCtrl](/ecosystem/nodes/cpp/integrating-with-prometheus).
* For technical assistance, contact [@mytonctrl\_help\_bot](https://t.me/mytonctrl_help_bot).

### 5.8 Monitor the efficiency

Set up dashboards to monitor validators using the APIs provided below.

1. Track penalized validators on each round with [@tonstatus\_notifications](https://t.me/tonstatus_notifications).
2. Use [Validation API](https://elections.toncenter.com/docs) to obtain information about current and past validation rounds (cycles) - including the timing of rounds, which validators participated, their stakes, and more. Information regarding current and past elections for each validation round is also available.
3. Use this [API](https://toncenter.com/api/qos/index.html#/) to obtain information about the efficiency of validators over time.

<Aside type="tip">
  This API analyzes data from the catchain to provide an estimate of a validator's efficiency. It serves as an alternative to the `checkloadall` utility.
  Unlike `checkloadall`, limited to validation rounds, this API supports any time interval for efficiency analysis.
</Aside>

**Workflow**

1. Check ADNL address of the validator:

   ```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
   MyTonCtrl> status
   ```

2. To the API, provide the ADNL address of the validator along with a time interval (`from_ts`, `to_ts`). For accurate results, choose a sufficient interval, such as 18 hours ago to the present moment.

3. Retrieve the result. If the efficiency percentage is below 90%, the validator is malfunctioning.

4. The validator must actively participate in validation and use the same ADNL address throughout the specified time period. For example, if a validator contributes to validation every second round, indicate the intervals during which they participated. Failing to do so may result in an inaccurate underestimate. This requirement applies not only to masterchain validators (with an index \< 100) but also to other validators (with an index > 100).

### 5.9 Learn slashing policy

If a validator processes less than 90% of the expected blocks during a validation round, they will be fined 101 TON.

Learn more about the [slashing policy](https://old-docs.ton.org/v3/documentation/nodes/validation/staking-incentives#decentralized-system-of-penalties).

### 5.10 Maintain validator

Stay vigilant on updates, monitor health status, and efficiency stability with dashboards.

## Verify

After completing the setup, confirm the validator is operating correctly:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
MyTonCtrl> status
```

Check the following indicators:

| Indicator                        | Expected value                          |
| -------------------------------- | --------------------------------------- |
| Local validator out of sync      | Less than 20 seconds                    |
| Masterchain out of sync          | Less than 20 seconds                    |
| Validator efficiency             | Above 90%                               |
| Validator index                  | Visible in status output                |
| Validator participation position | Between 200 and 250 for optimal staking |

<Aside type="tip">
  Validator efficiency may show 0% at the beginning of a cycle until the validator signs its first blocks. This is normal behavior.
</Aside>

Confirm that the validator participates in elections and recovers stakes on time by monitoring the pool balance in a [blockchain explorer](https://tonviewer.com/).

Confirm that the validator participates in elections and recovers stakes on time by checking the pool balance in a [blockchain explorer](/ecosystem/explorers/overview). For greater observability, [set up the monitoring](/ecosystem/nodes/cpp/run-validator#5-7-set-up-monitoring) of various validator metrics.

## Troubleshoot common issues

### Node is not synchronizing

* Verify that the validator UDP port is open: `sudo ufw status`.
* Check network connectivity to beacon nodes: `ping beacon-eu-01.toncenter.com -c 6`.
* Ensure disk IOPS meet minimum requirements. Re-run the [benchmark](/ecosystem/nodes/cpp/run-validator#disk-iops).
* Check service logs: `journalctl -u validator -f`.

### Validator efficiency is below 90%

* Confirm the node is fully synchronized (`Local validator out of sync` \< 20).
* Check disk performance. Slow storage is the most common cause of low efficiency.
* Verify that no other resource-intensive processes compete for CPU or RAM.
* Review hardware against [minimum requirements](/ecosystem/nodes/cpp/run-validator#1-2-minimal-hardware-requirements).

### Pool is not participating in elections

* Confirm that the pool is activated: `MyTonCtrl> pools_list` should show `Active` status.
* Verify the pool has sufficient balance for at least one cycle: `balance > min_stake`.
* Check that `single-nominator` mode is enabled: `MyTonCtrl> status_modes`.
* Ensure the validator wallet has enough TON for operational fees.

### Stake was not returned after a validation cycle

* Wait for the full cycle to complete. Stake recovery is not immediate.
* Check the elector contract status using a [blockchain explorer](/ecosystem/explorers/overview).
* Contact [@mytonctrl\_help\_bot](https://t.me/mytonctrl_help_bot) if the stake is not returned after the cycle ends.

### Pool contract is frozen

A pool contract may freeze if its entire balance is consumed by storage fees. This happens when too much time passes between pool creation and funding. Ensure you fund the pool promptly after activation.

## Support

Contact technical support [@mytonctrl\_help\_bot](https://t.me/mytonctrl_help_bot). This bot is for validators only and will not assist with questions for regular nodes.
