Files
smom-dbis-138/docs/channels/WATCHTOWER_AND_INDEXER.md
2026-03-02 12:14:09 -08:00

4.3 KiB
Raw Permalink Blame History

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 watchtowers 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 contracts 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.