65 lines
4.3 KiB
Markdown
65 lines
4.3 KiB
Markdown
# Watchtower and Indexer
|
||
|
||
Optional off-chain components for payment channels: watchtower (dispute response) and indexer (channel listing).
|
||
|
||
---
|
||
|
||
## Watchtower
|
||
|
||
### Purpose
|
||
|
||
When a channel is in **Dispute**, the party that did not initiate the close has a limited time (challenge window) to submit a **newer** signed state via `challengeClose`. If they are offline, a malicious counterparty could submit an old state and wait for the deadline, then `finalizeClose` and take more than their share.
|
||
|
||
A **watchtower** watches the chain for `ChallengeSubmitted` (and channel close activity) for channels where a designated participant is involved. If it sees a close that uses an older state than the one the watchtower holds, it submits `challengeClose` with the latest signed state before the deadline.
|
||
|
||
### Design
|
||
|
||
- **Inputs**: RPC URL, list of (channelId, latest signed state: nonce, balanceA, balanceB, sigs) for channels the user cares about, and a key that can sign txs (or the watchtower runs on behalf of the user and has delegated authority).
|
||
- **Logic**: Subscribe to or poll PaymentChannelManager for `ChallengeSubmitted` and `ChannelClosed`. For each channel in the list, if `ChallengeSubmitted` shows a dispute with `nonce` less than the watchtower’s latest nonce, call `challengeClose` with the stored state before `disputeDeadline`.
|
||
- **Security**: The key that signs `challengeClose` must be secure (env var, HSM, or user-backed key). Prefer a dedicated key with no other funds.
|
||
|
||
### Implementation options
|
||
|
||
- **Small service**: e.g. `services/watchtower/` in this repo: Node.js or Python script that uses ethers/web3.py, reads config from env, and runs a loop or event subscription.
|
||
- **Separate repo**: Standalone watchtower service that supports this contract’s ABI and events.
|
||
|
||
No watchtower implementation is included in this repo; this doc is the specification. Deploy and run a watchtower only if users need automated dispute response.
|
||
|
||
---
|
||
|
||
## Indexer
|
||
|
||
### Purpose
|
||
|
||
The frontend “Channels” tab lists channels by calling `getChannelCount` and `getChannelIdByIndex`, then `getChannel` for each. That works for a small number of channels. For many channels or for filtering by participant, an **indexer** can:
|
||
|
||
- Index `ChannelOpened` and `ChannelClosed` (and optionally `ChallengeSubmitted`).
|
||
- Expose an API: e.g. “channels where address X is participantA or participantB”, “channels in status Open/Dispute”.
|
||
|
||
### Design
|
||
|
||
- **Events**: `ChannelOpened(channelId, participantA, participantB, depositA, depositB)`, `ChannelClosed(channelId, balanceA, balanceB, cooperative)`, `ChallengeSubmitted(channelId, nonce, balanceA, balanceB, newDeadline)`.
|
||
- **Storage**: DB (e.g. Postgres) with tables for channels and events, keyed by chain and channelId.
|
||
- **API**: REST or GraphQL: e.g. `GET /channels?chainId=138&participant=0x...`.
|
||
|
||
### Implementation options
|
||
|
||
- **Existing Chain-138 / Mainnet indexer**: If the project already has an indexer for the chain, add handlers for PaymentChannelManager events and expose channel queries.
|
||
- **Subgraph (The Graph)**: Create a subgraph for PaymentChannelManager and query channels by participant.
|
||
- **Custom service**: Small service that subscribes to logs, writes to DB, and serves HTTP.
|
||
|
||
Document the indexer API and deployment in ops/deployment docs when one is added. Until then, the frontend uses on-chain `getChannelCount` + `getChannelIdByIndex` + `getChannel` only.
|
||
|
||
---
|
||
|
||
## Implementation status
|
||
|
||
- **Watchtower**: A minimal implementation lives in `services/watchtower/`. It subscribes to `ChallengeSubmitted` on PaymentChannelManager and calls `challengeClose` with a newer state from a JSON file before the dispute deadline. See `services/watchtower/README.md`.
|
||
- **Indexer**: No indexer or subgraph is implemented yet. Channels are enumerated on-chain by the frontend. To add "channels by participant", implement a custom indexer or The Graph subgraph as described above and expose an API (e.g. `GET /channels?participant=0x...`).
|
||
|
||
---
|
||
|
||
## Transaction mirroring (no change)
|
||
|
||
Channel transactions on **Chain-138** are normal txs. The existing **Transaction Mirroring Service** mirrors them to **TransactionMirror** on Mainnet. No change to that service or contract is required. State anchoring of Chain-138 (including PaymentChannelManager state) is already done by the **State Anchoring Service** and **MainnetTether**.
|