# Livre Relayer Operator Guide

This guide is for people who want to run a Livre-compatible Kora relayer.

## What Is A Relayer?

A relayer is a public service that submits a shielded withdrawal transaction
for a user. This lets someone withdraw to a recipient wallet that may have no
SOL yet, because the relayer pays the on-chain transaction fee.

In Livre, the wallet creates the note and zero-knowledge proof locally. The
relayer receives only a proof package that is already bound to the recipient,
nullifier, pool, amount, fee collector, and relayer address.

The relayer can:

- Check that a proof package is valid.
- Pay Solana gas for the withdrawal transaction.
- Earn the configured submitter fee if the withdrawal succeeds.
- Advertise peer relayers so wallets can fail over.

The relayer cannot:

- See or recover private note secrets.
- Change the recipient address.
- Change the withdrawal amount.
- Change the pool or nullifier.
- Spend the note twice.
- Take custody of user funds.

Livre differs from Tornado Cash in one important way: Livre pools may include
a configured protocol fee wallet plus a submitter fee for the relayer. The
relayer network itself is still permissionless; users can choose a public
relayer, paste a custom relayer URL, or use the desktop emergency self-pay path.

## What A Relayer Does

- Indexes shielded pool commitment/nullifier accounts.
- Serves public pool config and Merkle paths.
- Accepts proof-only withdrawal packages.
- Pays withdrawal gas as the transaction fee payer.
- Receives the submitter fee configured in the pool.
- Advertises peer relayer URLs so apps can fail over.

Kora is convenience infrastructure. Desktop direct withdraw can rebuild paths
from Solana RPC without Kora. Relayers still matter because they preserve the
better privacy default: the withdrawing user does not appear as the fee payer.

## Requirements

- Linux VPS or server with a public URL.
- Node.js 20 or newer.
- npm.
- Solana CLI, strongly recommended for key generation and balance checks.
- A funded relayer keypair.
- A reliable Solana RPC URL.
- The matching `shielded-pool-program` checkout for proof/index helper binaries.

For production, use HTTPS and run the service under systemd or another process
manager that restarts after reboot.

## 1. Install Runtime

Ubuntu/Debian example:

```bash
apt-get update
apt-get install -y git rsync nodejs npm build-essential pkg-config libssl-dev
```

Install Solana CLI from the official Solana release instructions, then verify:

```bash
solana --version
node -v
npm -v
```

## 2. Install Kora

Use the published Livre/Kora source URL when available:

```bash
git clone <kora-service-repo-url> /opt/chanis/kora-service
git clone <shielded-pool-program-repo-url> /opt/chanis/shielded-pool-program
cd /opt/chanis/kora-service
npm ci
```

For devnet testing from a local checkout, copying the folders with `rsync` is
also fine. Do not copy another relayer's database for mainnet operation; rebuild
from chain instead.

## 3. Create A Relayer Key

```bash
mkdir -p /opt/chanis/keys
chmod 700 /opt/chanis/keys
solana-keygen new --outfile /opt/chanis/keys/relayer.json
chmod 600 /opt/chanis/keys/relayer.json
solana-keygen pubkey /opt/chanis/keys/relayer.json
```

Fund that public key with enough SOL to pay transaction fees. The pool
submitter fee is what compensates relayers over time, but the hot key must have
SOL available before it can submit withdrawals.

Keep this key as a small hot wallet. Do not use your fee-collector wallet as a
relayer hot key unless you intentionally accept that operational risk.

## 4. Create The Env File

Create `/etc/chanis/kora-relayer.env`:

```bash
mkdir -p /etc/chanis
nano /etc/chanis/kora-relayer.env
chmod 600 /etc/chanis/kora-relayer.env
```

Template:

```dotenv
BASE_URL=https://your-relayer.example
KORA_RELAYER_URLS=https://your-relayer.example,https://another-relayer.example
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com

KORA_PROGRAM_ID=<shielded-pool-program-id>
KORA_VERIFIER_PROGRAM_ID=<verifier-program-id>
KORA_FEE_COLLECTOR=<final-fee-collector-wallet>
KORA_RELAYER_ADDRESS=<pubkey-from-relayer-json>
KORA_RELAYER_SECRET_KEY_FILE=/opt/chanis/keys/relayer.json
KORA_SHIELDED_POOL_DIR=/opt/chanis/shielded-pool-program

# Paste the production pool ladder exported by the Livre deployment.
KORA_SOL_POOLS='[]'
```

Important:

- `KORA_RELAYER_ADDRESS` must equal `solana-keygen pubkey` for the key file.
- `KORA_FEE_COLLECTOR` must match the pool accounts initialized on-chain.
- `KORA_SOL_POOLS` must match the deployed pool IDs/enums/fees.
- Do not use old devnet pool values on mainnet.

## 5. Rebuild The Index From Chain

```bash
cd /opt/chanis/kora-service
set -a
source /etc/chanis/kora-relayer.env
set +a
npm run index:rebuild -- --replace
```

This builds `data/kora-db.json` from Solana program accounts. It is the core
disaster-recovery property: a relayer can recover public commitment state
without trusting another relayer's private database.

## 6. Run Manually

```bash
cd /opt/chanis/kora-service
set -a
source /etc/chanis/kora-relayer.env
set +a
HOST=0.0.0.0 PORT=8787 node server.mjs
```

Health checks:

```bash
curl -sS http://127.0.0.1:8787/v1/health
curl -sS http://127.0.0.1:8787/v1/relayers
curl -sS http://127.0.0.1:8787/v1/pools/config
```

## 7. Install Systemd

From the Kora checkout:

```bash
cd /opt/chanis/kora-service
chmod +x deploy/install-systemd-node.sh
./deploy/install-systemd-node.sh \
  --name chanis-kora-relayer \
  --app-dir /opt/chanis/kora-service \
  --env-file /etc/chanis/kora-relayer.env \
  --port 8787
```

Useful commands:

```bash
systemctl status chanis-kora-relayer --no-pager
journalctl -u chanis-kora-relayer -f
systemctl restart chanis-kora-relayer
```

Put Nginx, Caddy, or another reverse proxy in front of port `8787` for HTTPS.

## 8. Preflight

Run preflight before asking wallets to use the relayer:

```bash
cd /opt/chanis/kora-service
set -a
source /etc/chanis/kora-relayer.env
set +a
npm run preflight -- --endpoint https://your-relayer.example
```

For mainnet, use:

```bash
npm run preflight -- --mainnet --endpoint https://your-relayer.example
```

The relayer is not ready until preflight returns OK.

## 9. Join The Relayer List

After preflight passes, publish these values:

- HTTPS base URL.
- Supported cluster.
- Relayer public key.
- Pool set / deployment tag.
- Operator contact, optional.

Livre wallets can use multiple relayers. Public relayers should list peers in
`KORA_RELAYER_URLS` so clients can discover backups. Advanced users should also
be able to paste a custom Kora URL in the app.

## Security Checklist

- Use a small hot relayer key, not treasury funds.
- Keep the fee collector separate from the relayer hot key.
- Back up `/etc/chanis/kora-relayer.env` without exposing private keys.
- Back up `data/kora-db.json`, but confirm rebuild from chain works.
- Monitor relayer SOL balance and `/v1/health`.
- Keep Node.js and server packages patched.
- Restrict SSH and use a firewall.
- Never paste private keys into public tickets, screenshots, commits, or docs.

## API Compatibility

A Livre-compatible relayer should support:

- `GET /v1/health`
- `GET /v1/relayers`
- `GET /v1/pools/config`
- `POST /v1/pools/sol/deposit/register`
- `GET /v1/pools/sol/{poolId}/path/{commitment}`
- `GET /v1/pools/sol/status/{commitment}`
- `POST /v1/pools/sol/withdraw/submit-proof`

The legacy relay route may remain for compatibility, but proof-only relaying is
the preferred privacy path.
