Testnet Setup¶
Complete procedure for wiping and setting up the testnet from scratch. This covers node deployment, genesis, and treasury distribution into multisig wallets.
Prerequisites¶
- SSH access to all 5 nodes (3 bootstrap as root, 2 providers as ubuntu)
- Go 1.24+ for building binaries and running setup scripts
- The genesis treasury seed (stored offline)
Node inventory¶
| Role | Host | SSH | API |
|---|---|---|---|
| Bootstrap | ldn.test.network | root@ldn.test.network |
https://ldn.core.test.network |
| Bootstrap | ffm.test.network | root@ffm.test.network |
https://ffm.core.test.network |
| Bootstrap | nyc.test.network | root@nyc.test.network |
https://nyc.core.test.network |
| Provider | 189.1.171.51 | ubuntu@189.1.171.51 |
— |
| Provider | 67.213.117.123 | ubuntu@67.213.117.123 |
— |
Step 1: Build¶
cd ~/workspace/xe-poc-2/core
GOOS=linux GOARCH=amd64 go build \
-ldflags "-X main.version=$(git describe --tags --always)" \
-o /tmp/xe ./cmd/xe/
Step 2: Stop all nodes¶
# Bootstrap nodes (pm2)
for host in ldn.test.network ffm.test.network nyc.test.network; do
ssh root@$host "pm2 stop xe-node"
done
# Provider nodes (systemd)
ssh ubuntu@189.1.171.51 "sudo systemctl stop xe-node"
ssh ubuntu@67.213.117.123 "sudo systemctl stop xe-node"
Step 3: Deploy binary and wipe data¶
# Bootstrap nodes
for host in ldn.test.network ffm.test.network nyc.test.network; do
scp /tmp/xe root@$host:/usr/local/bin/xe-node
ssh root@$host "rm -rf /var/lib/xe-node/ledger"
done
# Provider nodes
for host in 189.1.171.51 67.213.117.123; do
scp /tmp/xe ubuntu@$host:/tmp/xe-node
ssh ubuntu@$host "sudo cp /tmp/xe-node /usr/local/bin/xe-node && \
sudo chmod +x /usr/local/bin/xe-node && \
sudo rm -rf /var/lib/xe-node/ledger"
done
Data wipe deletes libp2p keys
If you also delete /var/lib/xe-node/host.key, new peer IDs will be generated on startup and you must update all dial configurations. Only delete the ledger/ subdirectory to preserve peer IDs.
Step 4: Start nodes¶
# Bootstrap nodes
for host in ldn.test.network ffm.test.network nyc.test.network; do
ssh root@$host "pm2 start xe-node"
done
# Provider nodes
ssh ubuntu@189.1.171.51 "sudo systemctl start xe-node"
ssh ubuntu@67.213.117.123 "sudo systemctl start xe-node"
Step 5: Verify genesis¶
Each node auto-applies the embedded genesis block on first boot, minting 100,000,000 XE to the treasury account.
for api in ldn.core.test.network ffm.core.test.network nyc.core.test.network; do
echo -n "$api: "
curl -s "https://$api/frontiers" | python3 -c \
"import sys,json; d=json.load(sys.stdin); print(len(d), 'accounts')"
done
All nodes should show 1 account (the genesis treasury).
Step 6: Treasury distribution¶
The genesis block mints to a single-key account. The setup script distributes the supply into four 2-of-3 multisig wallets:
| Wallet | Amount | Purpose |
|---|---|---|
| Treasury-A | 50,000,000 XE | Primary reserve |
| Treasury-B | 30,000,000 XE | Operations |
| Treasury-C | 10,000,000 XE | Grants / ecosystem |
| Treasury-D | 10,000,000 XE | Emergency reserve |
The script:
- Opens 4 multisig accounts (
multisig_open, 2-of-3 threshold) - Sends XE from genesis to each wallet
- Receives on each multisig wallet (1-of-N)
- Verifies all balances
- Prints key material for offline storage
Keys are deterministically derived from the genesis seed, so rerunning after a testnet wipe produces the same addresses.
Save key material
The script prints private seeds for all 12 multisig keys. Save these offline immediately. They are not stored anywhere else.
Optional: custom API endpoint¶
Step 7: Verify¶
Check the explorer to confirm:
- Genesis account has 0 XE remaining
- Four multisig accounts exist with correct balances
- Each multisig account shows "multisig 2 of 3" badge
- Blocks propagated to all nodes (check frontiers)
# Quick verification
for api in ldn.core.test.network ffm.core.test.network nyc.core.test.network; do
echo "$api:"
curl -s "https://$api/frontiers" | python3 -c \
"import sys,json; d=json.load(sys.stdin); print(f' {len(d)} accounts')"
done
Should show 5 accounts on each node (1 genesis + 4 treasury wallets).
Token model summary¶
After setup, the testnet has:
| Token | Supply | Source |
|---|---|---|
| XE | 100,000,000 (fixed) | Genesis block, distributed to 4 multisig wallets |
| XUSD | Unlimited (faucet) | 100 XUSD per claim, once per account per 24 hours |
- XE cannot be claimed. New XE enters circulation only via lease settlement (provider emission).
- XUSD is the testnet faucet token. Any account can claim 100 XUSD per day via
xe fund. - Voting weight is based on XUSD balance, not XE.
Peer ID recovery¶
If peer IDs change (full data wipe including host.key), get new multiaddrs from logs:
for host in ldn.test.network ffm.test.network nyc.test.network; do
echo -n "$host: "
ssh root@$host "pm2 logs xe-node --lines 200 --nostream --no-color 2>/dev/null" \
| grep "Listening on: /ip4/" | grep -v "127.0.0.1\|172.17" | head -1 \
| grep -oP '/ip4/.+'
done
Then update PM2 configs (bootstrap) and systemd unit files (providers) with the new -dial addresses.