# Sarmad VPS Coordinator

Lightweight Node.js service for the Sarmad phone network.

## Role

- Accept **heartbeats** from phones (app open + node running)
- Freeze an **active set** for each production cycle
- Publish a **cycle seed** so phones compute the same fair shuffle locally
- Skip offline producers after **blockTime + half-block grace**
- Public **status page**: chain height, active count, countdown only (no next-miner identity)
- Optional **authenticated reset** (`POST /v1/reset`) for development network wipe

Does **not** replace your bot service. Run it on another port (default `9334`).

## Run

```bash
cd vps_scheduler
node server.js
```

Optional env:

```bash
export SARMAD_COORD_PORT=9334
export SARMAD_COORD_HOST=0.0.0.0
export SARMAD_HEARTBEAT_TTL_MS=90000
# Required to enable Reset Network from the DEV Android app (omit to keep /v1/reset disabled → 503)
export SARMAD_RESET_TOKEN='a1b2c3d4e5f6789012345678abcdef0123456789abcdef0123456789abcdef01'
node server.js
```

### Multi-VPS cluster (scaffold; single-VPS default)

Leave these unset for today's one-coordinator behaviour (`clusterEnabled: false`, always leader).

When you add a second VPS, set the same peer list on every node (include self):

```bash
export SARMAD_VPS_SELF_URL=http://78.47.21.219:9334
export SARMAD_VPS_CLUSTER=http://vps1:9334,http://vps2:9334
export SARMAD_VPS_LEADER_TTL_MS=45000   # optional; leader silence → failover
# optional stable id (defaults to SELF_URL):
# export SARMAD_VPS_ID=vps1
```

Behaviour when enabled:

- One leader at a time; followers are hot standbys (same registry, watch-only)
- Handoff on leader silence (timeout); new leader opens a **fresh** live shuffle (choice B)
- Do not rotate leadership just because a produce-queue emptied
- Followers sync tip from leader and forward `/v1/tx` + `/v1/block-report`
- `/v1/status` and `/v1/cluster` expose `clusterEnabled`, `isLeader`, `leaderUrl`, `queueLength`
- Phones/EXE: sticky home VPS + follow `leaderUrl` (re-probe peers if leader dies)

#### Preferred leader (optional)

By default the leader is whichever peer sorts first lexicographically. To make a
specific peer the normal leader — for example a machine with better hardware, or
a PC running at home — set the same priority list on **every** peer:

```bash
export SARMAD_VPS_LEADER_PRIORITY=http://pc:9336,http://vps1:9334,http://vps2:9335
export SARMAD_VPS_RECLAIM_AFTER_MS=180000        # optional; default max(3×TTL, 120000)
export SARMAD_VPS_RECLAIM_MAX_LAG_BLOCKS=2       # optional
```

Cold-start election is unchanged. A preferred peer only takes over through the
existing planned-handoff ACK barrier, and only after it has been continuously
reachable for `SARMAD_VPS_RECLAIM_AFTER_MS` *and* is within
`SARMAD_VPS_RECLAIM_MAX_LAG_BLOCKS` of the tip. Any missed status probe resets
the streak, which is what stops an unreliable peer from flapping leadership.
Leaving `SARMAD_VPS_LEADER_PRIORITY` unset keeps the original behaviour exactly.

```bash
export SARMAD_VPS_STEP_DOWN_WHEN_ISOLATED=1      # default off
```

Opt-in: a leader that cannot reach any peer for `SARMAD_VPS_LEADER_TTL_MS` stops
acting as leader rather than producing blocks the rest of the cluster cannot see.
Set this only on peers behind an unreliable link (home connection, SSH reverse
tunnel). Leave it off on a VPS, so the last surviving VPS keeps leading.

See `tools/local-vps-cluster/README.md` for a worked setup that makes a Windows PC
the main coordinator with automatic fallback to the VPS peers.

Generate a strong token (example only — do not commit real secrets):

```bash
openssl rand -hex 32
```

### Reset endpoint

- `POST /v1/reset` clears the active-node registry and resets cycle/height/tip/countdown to genesis defaults.
- Clients must send header `X-Sarmad-Reset-Token` matching `SARMAD_RESET_TOKEN`.
- Missing/wrong token → `403`. Token not configured on the VPS → `503` (endpoint disabled).
- The token is never included in `/v1/status` or other public responses. Do not log it.

On the Android app, set `ProtocolConstants.COORDINATOR_RESET_TOKEN` to the **same** value. That constant is DEV-only and extractable from an APK — treat it as a development secret only.

## systemd

Create `/etc/systemd/system/sarmad-coordinator.service` pointing at this folder, for example:

```ini
[Unit]
Description=Sarmad VPS Coordinator
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/sarmad-coordinator
ExecStart=/usr/bin/node server.js
Restart=on-failure
Environment=SARMAD_COORD_PORT=9334
Environment=SARMAD_COORD_HOST=0.0.0.0
Environment=SARMAD_HEARTBEAT_TTL_MS=90000
Environment=SARMAD_RESET_TOKEN=a1b2c3d4e5f6789012345678abcdef0123456789abcdef0123456789abcdef01

[Install]
WantedBy=multi-user.target
```

Replace the example token with your own `openssl rand -hex 32` value. Then:

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now sarmad-coordinator
```

After updating `server.js`, copy the new file to the VPS and `sudo systemctl restart sarmad-coordinator`.

## Point the Android app

Set `ProtocolConstants.COORDINATOR_BASE_URL` to `http://YOUR_VPS_IP:9334` (or HTTPS via nginx reverse proxy).

## Website

Open `http://YOUR_VPS_IP:9334/` — or reverse-proxy `/` of your existing site to this service’s status endpoints.
