# Join Testnet Subnet

## Requirements

* Linux Environment
  * If on Windows 10-11, follow the [WSL documentation](/subnet-template/troubleshooting.md#running-on-windows-using-wsl)
* Python 3.10 or higher

***

## Install

```
git clone https://github.com/hypertensor-blockchain/subnet-template.git
cd subnet-template
python -m venv .venv
source .venv/bin/activate
pip install .
touch .env
```

Copy and paste the `.env.example` variables to the newly generated `.env` file. The main variable required to run the subnet node in this documentation is the `DEV_RPC` variable.

***

<details>

<summary>Run in DEBUG Mode (Optional)</summary>

Configure your logger and set the debug level to DEBUG to show the debug messages.

{% hint style="info" %}
This is an optional step meant for debugging the subnet template and the P2P daemon.
{% endhint %}

```python
export SUBNET_LOGLEVEL=DEBUG
```

</details>

***

In the following, we'll have to manage all of the unique keys for each node deployed:

**Copy and paste the following somewhere:**

Fill this out as you go along each step as a reference for the later steps.

{% hint style="info" %}
You can use a .txt file in the following, but ensure **not to use a .txt file with markdown** because it will produce hidden characters; most command interfaces will include them and break CLI commands.
{% endhint %}

1. **Coldkey**
   1. **Address**: `<address>`
   2. **Private key**: `<private key>`
2. **Hotkey**
   1. **Address**: `<address>`
   2. **Private key**: `<private key>`
3. **Peer ID**
   1. **Address**: `<address>`
   2. **Path of peer ID private key**: `<path>`
4. **Client Peer ID**
   1. **Address**: `<address>`
   2. **Path of client peer ID private key**: `<path>`
5. **Bootnode Peer ID**
   1. **Address**: `<address>`
   2. **Path of bootnode peer ID private key**: `<path>`
6. **Public IP**: `<public ip>`
7. **Port**: `<port>`

***

For each command, you can run `<command> --help` for information.

***

### 1. Generate Coldkey and Hotkey

Once both keys are generated, it will output the mnemonic phrase, private key, and address. Store the information in a safe place.

#### Generate Coldkey

You can also use your coldkey generated by your [wallet](/blockchain/wallet.md) instead of the CLI.

```bash
generate-key --words 12
```

Save the coldkey **private key** in a safe space to be used later when registering the node on-chain.

#### Generate Hotkey

```bash
generate-key --words 12
```

Save the hotkey **private key** in a safe space to be used later when starting the subnet node.

***

### 2. Generate Private Keys

Generate 3 private keys for your peer IDs: the **main peer ID**, the **bootnode peer ID**, and the **client peer ID**. This will automatically generate 3 private key files that you will see in the root directory.

**Save all 3 peer IDs in the logs in a safe place** for later steps.

{% hint style="info" %}
If running multiple nodes on a single server, ensure all paths are unique.
{% endhint %}

```bash
keygen \
--path main-node01.key \
--bootstrap_path bootnode-node01.key \
--client_path client-node01.key \
--key_type ed25519
```

***

### 3. Fund Keys

Visit the [Discord faucet](/testnet/faucet.md) and fund both the coldkey and hotkey.

{% hint style="info" %}
It is suggested to fund the coldkey from the faucet and **send 1 TENSOR to the hotkey from the coldkey** via the [wallet](/blockchain/wallet.md) on the [explorer](/testnet/explorer.md). The hotkey is used for consensus, and while running consensus does not have block fees, all wallets are required to have a minimum of 0.0000000000000005 TENSOR to be a live account. By sending the hotkey 1 TENSOR, you will accomplish this requirement.
{% endhint %}

The **coldkey will need at least 100 TENSOR** to stake on registration, plus a dynamic burn fee. The faucet will give 500 TENSOR for each request and should be sufficient. If not, contact us on Discord.

1. Use the [faucet](/testnet/faucet.md) to fund the coldkey
2. Send 1 TENSOR from the coldkey to the hotkey, or use the [faucet](/testnet/faucet.md) (faucet may have a cooldown, if so, use the wallet)

***

### 4. Register Subnet Node

Register the subnet node on-chain and retrieve your subnet node ID. **Put the subnet node ID somewhere** to be used for later steps.

Run `register-node --help` or visit `subnet/subnet_cli/node/register.py` to view the full list of available arguments.

**Before running:**

* Know what your coldkey and hotkey are
* Know what subnet ID you're registering to
* Know your peer IDs
* Have the coldkey private key ready

```bash
register-node \
--subnet_id 2 \
--hotkey ADD_HOTKEY_ADDRESS_HERE \
--peer_id ADD_MAIN_PEER_ID_HERE \
--bootnode_peer_id ADD_BOOTNODE_PEER_ID_HERE \
--client_peer_id ADD_CLIENT_PEER_ID_HERE \
--delegate_reward_rate 0.125 \
--stake_to_be_added 200.00 \
--max_burn_amount 100.00 \
--private_key ADD_PRIVATE_KEY_OF_COLDKEY_HERE
```

{% hint style="danger" %}
In production, the subnet node should never use the coldkeys private key here. The node should be registered using the CLI (coming soon).
{% endhint %}

***

### 5. Run Node

We suggest using a terminal multiplexer or similar of your choosing, such as [tmux](https://github.com/tmux/tmux/wiki) or [pm2](https://pm2.keymetrics.io/docs/usage/quick-start/).

#### Before running:

* Get the server's IP you're running the node from
* Ensure you have no firewalls blocking connections
* Choose and open a port
  * Replace `31330` with the port of your choosing in all 4 locations
* Have your subnet node ID
* Have your main identity path generated in the [Generate Private Keys](#generate-private-keys) step
* Ensure your hotkey is funded with at least 0.0000000000000005 TENSOR

{% code overflow="wrap" %}

```bash
subnet-server-mock \
--host_maddrs /ip4/0.0.0.0/tcp/31330 /ip4/0.0.0.0/udp/31330/quic-v1 \
--announce_maddrs /ip4/YOUR_PUBLIC_IP/tcp/31330 /ip4/YOUR_PUBLIC_IP/udp/31330/quic-v1 \
--identity_path main-node01.key \
--subnet_id 2 \
--subnet_node_id ADD_SUBNET_NODE_ID \
--private_key ADD_PRIVATE_KEY_OF_HOTKEY HERE \
--initial_peers /ip4/18.188.231.198/tcp/31330/p2p/12D3KooWGv47krKG6j6MtGLdLYqJHratRJKx9xFTsDbzTTUPNgUB
```

{% endcode %}

{% hint style="info" %}
If **connecting to a bootnode fails, there is a 20 second cooldown**. For each failed attempt, you cannot connect to the subnet for at least 20 seconds.
{% endhint %}

**Once run, you will see many logs, including:**

```bash
[INFO] Initializing PoS - proof-of-stake
[INFO] About to run DHT
...
[INFO] About to begin consensus
```

**If you do see** `Server is not accessible directly to the majority of all peers, attempting to connect directly anyway`**, the server either has one of the following issues:**

* Firewall is not accepting connections
* The public IP argument is incorrect
* Port is closed for incoming and or outgoing connections

**Note**: This log can also arise if peers are exiting or busy. If you verify that there are no firewall blocking the connection, the port is open, and the public IP is correct, then continue running the node.

{% hint style="info" %}
If you cannot resolve this issue, continue running the node as a relay node.
{% endhint %}

**How to resolve network issues:**

* Ensure that your Internet provider gives you a public IP address
* Choose a specific port for the subnet template server, for example, 31330
* If you have a firewall or NAT, configure it to allow incoming connections to the chosen TCP port
* Start the server and ensure it logs `This server is accessible directly`

If all of these issues are already resolved and the node continues to have these issues when starting, the network will attempt to force the node to connect directly. While running the node, if you receive a ValidationError about 'Peer x can't access this node. Probably, libp2p has failed to bypass the firewall, then you likely have a firewall blocking the connection on the port or IP itself.

Keep this running **forever**.

***

## Run Multiple Nodes

Test the scalability of the Subnet Template by running multiple nodes from a single server.

#### Repeat steps 1-5 for each node, using a separate command prompt for each.


---

# 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.hypertensor.org/subnet-template/quick-starts/join-testnet-subnet.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.
