> For the complete documentation index, see [llms.txt](https://docs.pharos.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pharos.xyz/node-and-validator-guide/node-management.md).

# Node Management

This guide covers [Atlantic testnet](/getting-started/network/atlantic-testnet.md) and [Pacific mainnet](/getting-started/network/pacific-mainnet.md).

|                                       | Atlantic testnet                     | Pacific mainnet                 |
| ------------------------------------- | ------------------------------------ | ------------------------------- |
| Minimum stake required for activation | **100,000 PROS**                     | **1,000,000 PROS**              |
| Ops activation example                | `--stake 100000` (override required) | `--stake 1000000` (ops default) |

{% hint style="info" %}
Use the same network throughout: node configuration, container, RPC, and owner wallet. Select the matching network in each example below. Ops defaults to 1,000,000 PROS; explicitly set `--stake 100000` for the Atlantic activation example.
{% endhint %}

### Node Initialization

Complete the Docker Compose setup for your network using the deployment guide linked below. To create and start the container for the first time, run this from the workspace containing `docker-compose.yml`:

```sh
docker compose up -d
```

Use `docker-compose up -d` if your installation uses the standalone Compose command.

If the container already exists but is stopped, use the matching `docker start` command below.

#### Atlantic testnet

Follow [Using Docker (Atlantic Testnet)](https://github.com/PharosNetwork/docs/tree/main/node-and-validator-guide/validator-node-deployment/using-docker-atlantic.md), which uses `container_name: atlantic-testnet`.

```sh
docker start atlantic-testnet
```

#### Pacific mainnet

Follow [Using Docker](/node-and-validator-guide/validator-node-deployment/using-docker-deployment.md) and select the **For Mainnet** downloads (`mainnet.genesis` and `mainnet.version`). Its Compose example uses `container_name: pharos-node`.

```sh
docker start pharos-node
```

If you customized `container_name` in `docker-compose.yml`, use your container name in the `docker start` and `docker exec` commands.

#### Keys and ops

On first start, the Docker image automatically generates the node's cryptographic keys in `keys/` under the mounted data directory, including `domain.pub`, `stabilizing.pub`, and their private-key files. The image also copies `ops` to the data directory on each start; see the [Docker directory structure](/node-and-validator-guide/validator-node-deployment/using-docker-deployment.md#directory-structure). No manual `./ops generate-keys` step is needed for Docker deployment.

⚠️ Protect the private keys in `keys/` and keep secure backups.

### Entering the container

With the container running, open a shell for your network:

#### Atlantic testnet

```sh
docker exec -it atlantic-testnet /bin/bash
```

#### Pacific mainnet

```sh
docker exec -it pharos-node /bin/bash
```

#### Working directory

Run node and `./ops` commands from the mounted data directory (`/data` inside the container), where `ops` and `keys/` are available. Commands in the container can access the node's local keys and local RPC. Continue with [Join validator sets](#join-validator-sets) to generate an unsigned registration transaction using `./ops`.

### Join validator sets

#### Prerequisites

⚠️ The registration sender becomes the permanent validator owner (the Safe address when using a Safe). Changing the owner is not supported. A hardware wallet or Safe multisig is mandatory.

Use the latest [ops tool](https://github.com/PharosNetwork/ops#register-as-validator) and your initialized node's existing public-key files.

⚠️ The domain public key must be the real node key from `keys/domain.pub`, never empty or a placeholder. An empty `_publicKey` produces `poolId = sha256("")` and collides with other empty-key registrations.

The required flags are `--domain-label` (validator name) and `--domain-endpoint` (public endpoint). The endpoint must be reachable by other nodes and use TCP with the consensus port (default: `19000`): `tcp://YOUR_PUBLIC_IP:19000` or `tcp://yourdomain:19000`. Do not use `127.0.0.1` or `localhost` as the validator endpoint.

#### Generate unsigned registration

Replace the validator name and public endpoint below with your own. The examples use the node's existing `./keys/domain.pub` and `./keys/stabilizing.pub` files; these are also the defaults when the key-path flags are omitted. If your files are elsewhere, supply their actual paths.

{% tabs %}
{% tab title="Atlantic testnet" %}
Use the [Atlantic RPC](/getting-started/network/atlantic-testnet.md). Explicitly set `--stake 100000` to meet Atlantic's **100,000 PROS** activation threshold and override the ops default of 1,000,000 PROS.

```sh
./ops add-validator \
  --domain-label "my-validator" \
  --domain-endpoint "tcp://YOUR_PUBLIC_IP:19000" \
  --rpc-endpoint "https://atlantic.dplabs-internal.com" \
  --domain-pubkey "./keys/domain.pub" \
  --stabilizing-pubkey "./keys/stabilizing.pub" \
  --stake 100000 \
  --unsigned
```

{% endtab %}

{% tab title="Pacific mainnet" %}
Use the [Pacific mainnet RPC](/getting-started/network/pacific-mainnet.md). `--stake 1000000` meets mainnet's **1,000,000 PROS** activation threshold and matches the ops default.

```sh
./ops add-validator \
  --domain-label "my-validator" \
  --domain-endpoint "tcp://YOUR_PUBLIC_IP:19000" \
  --rpc-endpoint "https://rpc.pharos.xyz" \
  --domain-pubkey "./keys/domain.pub" \
  --stabilizing-pubkey "./keys/stabilizing.pub" \
  --stake 1000000 \
  --unsigned
```

{% endtab %}
{% endtabs %}

#### Understand the unsigned output

`--unsigned` prints the staking contract address, value in wei, method, calldata, and function ABI without signing or broadcasting. `VALIDATOR_PRIVATE_KEY` is not required in this mode.

* **Contract / To:** staking contract `0x4100000000000000000000000000000000000000` on both networks.
* **Method:** `registerValidator`, a payable function that registers the node and locks the supplied stake.
* **Calldata / Data:** the encoded function call, including the description, public keys, proofs of possession, and endpoint. Copy the complete hex string without line breaks.
* **Value:** the stake sent with the transaction as `msg.value`, expressed in wei. The stake is not a separate function parameter.
* **Function ABI:** the function definition used to decode calldata or enter parameters individually in a wallet.

#### Stake amount and units

`--stake` is in **PROS tokens**. Ops converts it to wei: **1 PROS = 10^18 wei**. Use the amounts for your network's example:

{% tabs %}
{% tab title="Atlantic testnet" %}

| Input or output                    | Amount                         |
| ---------------------------------- | ------------------------------ |
| Ops `--stake`                      | `100000` PROS                  |
| Safe value / browser wallet amount | `100000` PROS                  |
| Ops value / Cast `--value`         | `100000000000000000000000` wei |
| {% endtab %}                       |                                |

{% tab title="Pacific mainnet" %}

| Input or output                    | Amount                          |
| ---------------------------------- | ------------------------------- |
| Ops `--stake`                      | `1000000` PROS                  |
| Safe value / browser wallet amount | `1000000` PROS                  |
| Ops value / Cast `--value`         | `1000000000000000000000000` wei |
| {% endtab %}                       |                                 |
| {% endtabs %}                      |                                 |

⚠️ Safe's value field uses **PROS**, not wei. If you change `--stake`, regenerate the unsigned output and match the wallet amount or Cast value to it. Keep enough PROS available for transaction fees in addition to the stake.

Choose one submission method below. Submit from your intended owner wallet on the same network as your node and RPC.

#### Submit via Safe

**Atlantic testnet**

Use an **Atlantic testnet Safe UI** and a Safe wallet on Atlantic (chain ID **688689**). Set **Value** to `100000` **PROS** for the Atlantic example. Verify the network against the [Atlantic network information](/getting-started/network/atlantic-testnet.md).

**Pacific mainnet**

Use [Pharos Safe](https://safe.pharosnetwork.xyz/) for **Pacific mainnet** (chain ID **1672**). Set **Value** to `1000000` **PROS** for the mainnet example. Verify the network against the [Pacific network information](/getting-started/network/pacific-mainnet.md).

**Build and execute the transaction**

1. Open the intended owner Safe's transaction builder and set **To** to `0x4100000000000000000000000000000000000000`.
2. Set **Value** in **PROS** to match the unsigned registration for your network, using the amounts above.
3. Enable **custom data** (recommended) and paste the generated calldata into **Data**, with no newlines or line breaks.
4. Review the network, Safe address, destination, value, and calldata. Collect the required Safe signer approvals and execute the transaction.

Alternatively, disable **custom data**, load the function ABI printed by ops, and select `registerValidator`. Enter its six string parameters individually: description, public key, public-key proof of possession, BLS public key, BLS proof of possession, and endpoint, in ABI order. Use the exact values decoded from the generated calldata, and keep the same **PROS** value.

To obtain those values with Cast (included in [Foundry](https://www.getfoundry.sh/)):

```sh
cast decode-calldata \
  "registerValidator(string,string,string,string,string,string)" \
  "YOUR_CALLDATA_PRINTED_BY_OPS"
```

Replace the data placeholder with the complete generated calldata. Enter each decoded string's contents without the surrounding display quotes.

#### Submit via hardware wallet and browser extension

Using MetaMask as an example:

1. Connect your hardware wallet, select the intended owner account, and add or switch to your node's network using the [Atlantic testnet](/getting-started/network/atlantic-testnet.md) or [Pacific mainnet](/getting-started/network/pacific-mainnet.md) network information.
2. In **Settings → Transactions**, enable **Show Hex Data**.
3. Click **Send**, choose **PROS**, and set **To** to `0x4100000000000000000000000000000000000000`.
4. Set **Amount** in **PROS** to match your generated stake (`100000` for the Atlantic example or `1000000` for the Pacific mainnet example). Paste the generated calldata into **Hex data**, with no newlines or line breaks.
5. Click **Continue**, review the transaction details, then confirm and sign with your hardware wallet to send it.

#### Optional: submit via Cast and Ledger

Install [Foundry](https://www.getfoundry.sh/) to use `cast`, then connect and unlock your Ledger. Use your network's example and replace the data placeholder with the complete calldata printed by ops, on one line:

{% tabs %}
{% tab title="Atlantic testnet" %}
This uses the [Atlantic RPC](/getting-started/network/atlantic-testnet.md) and the value for `--stake 100000`:

```sh
cast send 0x4100000000000000000000000000000000000000 \
  --ledger \
  --rpc-url "https://atlantic.dplabs-internal.com" \
  --value 100000000000000000000000 \
  --data "YOUR_CALLDATA_PRINTED_BY_OPS"
```

{% endtab %}

{% tab title="Pacific mainnet" %}
This uses the [Pacific mainnet RPC](/getting-started/network/pacific-mainnet.md) and the value for `--stake 1000000`:

```sh
cast send 0x4100000000000000000000000000000000000000 \
  --ledger \
  --rpc-url "https://rpc.pharos.xyz" \
  --value 1000000000000000000000000 \
  --data "YOUR_CALLDATA_PRINTED_BY_OPS"
```

{% endtab %}
{% endtabs %}

The unsuffixed Cast `--value` is in **wei**. If you generated a different stake, use its printed wei value. Check that the Ledger account is your intended permanent owner before approving the transaction on the device.

#### Stake requirements

* **Registration:** minimum **100 PROS**; accepted registration stake is **100–50,000,000 PROS**.
* **Atlantic testnet staking/activation:** total stake (self-stake + delegators) must reach **100,000 PROS**.
* **Pacific mainnet activation:** total stake (self-stake + delegators) must reach **1,000,000 PROS**. Registering with at least this amount activates the validator at the next epoch.

Registration below the network's activation threshold leaves the validator in the bootstrapping state until sufficient total stake is reached. Registering with 100 PROS alone does not activate a validator on either network.

#### Check node health

After registration, check the node's health with the ops command:

```sh
./ops health-check
```

#### Test network connectivity

Then test network connectivity to other validators:

```sh
./ops network-test
```


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pharos.xyz/node-and-validator-guide/node-management.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
