# Keeper & provider operations (Fletcher)

For users who want to **operate** randomness — run a keeper that fulfills push-flow callbacks, or
register their own hash-chain provider. Most integrators do **not** need this; they consume the
default provider + the protocol's keeper. Read this only when the user explicitly wants to run
infrastructure.

## Mental model

A **provider** commits a hash chain up front: `commitment = keccak256^chainLength(seed)`. Each
request consumes one link; the provider reveals `revelationOf(seed, chainLength, seq)` for sequence
`seq`. The chain is walked backwards from the tip, so revealing link `seq` never exposes future
links. When the chain nears exhaustion, the provider **rotates** onto a fresh seed.

The **keeper (Fletcher)** is the automation: it watches `RandomnessRequested` events for push-flow
requests and calls `revealWithCallback` with the correct provider revelation, settling the
consumer's callback. The same operator usually runs both (one provider + its keeper).

## Fletcher CLI

`@quiver/fletcher` (bin: `fletcher`). Run via `pnpm --filter @quiver/fletcher fletcher <cmd>` or the
built `dist/index.js`. Commands:

| Command | Purpose |
|---|---|
| `genseed` | Generate a fresh 32-byte seed (keep it secret). |
| `register` | Register the signer as a provider: commits `keccak256^length(seed)`, sets fee, chain length, and reveal URI. |
| `run` | Start the keeper loop — watch for requests and fulfill callbacks. |
| `info` | Print the on-chain provider record (commitment, seq, fee, chain length). |
| `revelation <seq>` | Print the provider revelation for a sequence number (pull-flow support / debugging). |
| `rotate <newSeedHex> <length>` | Rotate onto a fresh hash chain (extend an exhausted chain or replace a compromised seed). |

## Configuration (`fletcher.env`)

Copy `fletcher.env.example` → `fletcher.env`, `chmod 600`, and fill in secrets. Never commit it.
Key variables:

- `FLETCHER_NETWORK` — `rh_mainnet` | `rh_testnet` | `local`.
- `RH_MAINNET_RPC_URL` — use a **dedicated** RPC in production; public endpoints rate-limit and make
  the keeper miss events.
- `QUIVER_COORDINATOR_ADDRESS` — `0x8cF4f562301fA966F153eE1e3D46D975DF21C9a3` (mainnet) /
  `0x1da30d6465f657F11B4D7F6Db0B16aD79152fb40` (testnet).
- Signer — either a Foundry keystore (`FLETCHER_KEYSTORE` + `KEYSTORE_PASSWORD`, recommended) or a
  raw `PRIVATE_KEY`.
- `FLETCHER_SEED` — the 32-byte seed whose commitment is registered on-chain (**secret**).
- `FLETCHER_CHAIN_LENGTH` (e.g. `100000`), `FLETCHER_ANCHOR` (bump after each rotation),
  `FLETCHER_FEE_WEI`.
- Tuning: `FLETCHER_BACKFILL_BLOCKS` (startup look-back for missed requests), `FLETCHER_POLL_MS`.

## Typical operator flow

```bash
# 1. Generate and safely store a seed, then register as a provider.
fletcher genseed            # → put the value in FLETCHER_SEED (secret)
fletcher register           # commits keccak256^length(seed), sets fee + URI
fletcher info               # verify the on-chain record

# 2. Run the keeper (fulfills push-flow callbacks continuously).
fletcher run

# 3. When the chain nears exhaustion, or to retire a compromised seed:
fletcher rotate <newSeedHex> <length>   # then bump FLETCHER_ANCHOR
```

Run `fletcher run` as a persisted service (systemd/Docker). A `Dockerfile` and
`docker-compose.yml` ship in the repo (keystore mounted read-only at `/keystores`). Deep runbook,
systemd unit, and rotation guidance: https://quiver.foundation/docs/fletcher-operations

## Security notes

- The seed and keystore password are the two secrets that matter. Anyone with the seed can predict
  every future revelation for the current chain segment — rotate immediately if exposed.
- Fairness holds as long as **either** the provider or the requester is honest, so a provider cannot
  bias results alone. But a provider that reveals selectively can withhold service — run a reliable
  keeper and monitor for `CallbackFailed`.
- Keep the keeper's signer funded for gas; it pays to submit reveals.
