> For the complete documentation index, see [llms.txt](https://docs.mineglyph.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mineglyph.xyz/architecture/indexer-signer.md).

# Indexer & signer

The indexer and signer run together as one off-chain service. The indexer turns wallet history into a hashrate; the signer attests to it so the contract will accept it.

## Indexer

For a given wallet, the indexer:

1. Reads the wallet's transaction history — from a block explorer API when available (full metrics), or from raw RPC as a fallback.
2. Computes the four metrics (age, transactions, volume, hold time) against the **epoch snapshot** — the start of the current epoch, not the live moment.
3. Applies the log-scaled [hashrate formula](/protocol/hashrate.md).
4. Caches the result per `(wallet, epoch)` so the number is stable within an epoch.

Metrics are **not** stored in a persistent database of all users — they are computed on demand and cached briefly in memory. Only wallets that actually register have their hashrate written on-chain.

### Data sources

* **Explorer (preferred):** a Blockscout-compatible API gives full metrics including volume and hold time.
* **RPC fallback:** without an explorer, transaction count comes from the account nonce and wallet age from a binary search over historical state; volume and hold default to 0, producing a conservative (never inflated) score.

## Signer

The signer holds a trusted private key whose public address is set as the `signer` in the `GlyphMining` contract. On request it signs an EIP-712 typed message:

```
HashrateUpdate {
  address wallet;
  uint256 hashrate;
  uint256 epoch;
  uint256 nonce;
  uint256 expiry;
}
```

bound to a domain of `("GlyphMining", "1", chainId, contractAddress)`. That binding means a signature is valid **only** for the exact contract on the exact chain — it can't be replayed elsewhere.

### The critical rule

**The signer never signs a hashrate supplied by the client.** The `/sign` endpoint takes only a wallet address; the hashrate is always recomputed server-side from chain data. A forged number from a caller is ignored. This is covered by tests.

## The HTTP API

| Method | Path                | Purpose                                            |
| ------ | ------------------- | -------------------------------------------------- |
| GET    | `/health`           | status, signer address, current epoch              |
| GET    | `/hashrate/:wallet` | metrics + hashrate breakdown (no signature)        |
| POST   | `/sign`             | recompute server-side, return a signed attestation |

## Operational security

* The **signer private key** is never committed to the repository. It lives only in the host's secret manager and is kept separate from the deployer key.
* If the key is ever compromised, the protocol owner rotates it on-chain via `setSigner()`; old signatures stop working immediately.
* The endpoints are **rate-limited** per IP, with a stricter limit on `/sign`.
* Standard hardening (security headers, CORS allow-list, input validation) is applied, and errors never leak internal details.

See [Security model](/security/security-model.md) for how these off-chain guarantees combine with on-chain enforcement.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.mineglyph.xyz/architecture/indexer-signer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
