Watcher Topology & Node Model
Watcher nodes are the decentralized observers of the SLASettle protocol. They bridge off-chain service health to the on-chain consensus state in watcher_registry.
Node Lifecycle & Authorization
In the current protocol implementation:
- Curated Node Committee: Watcher addresses are authorized on-chain by the registry administrator via
watcher_registry.register_watcher(admin, watcher_address). - Identity Verification: When submitting a check, the transaction must be signed by the watcher account (
watcher.require_auth()). - De-Registration: If an operator goes offline or misbehaves, the administrator can revoke authorization via
remove_watcher(admin, watcher_address). De-registration decrementsWatcherCountwithout affecting tallies of previously finalized rounds.
Round Synchronization
Rounds define discrete observation windows during which watchers probe target services and submit votes.
- Round Identification: Rounds are indexed by a monotonically increasing 64-bit integer (
round_id). - Time Calculation: The watcher daemon computes the active round based on epoch seconds: $$\text{round_id} = \left\lfloor \frac{\text{unix_timestamp}}{\text{ROUND_LENGTH_SECONDS}} \right\rfloor$$
- Standard Round Duration: Testnet configurations typically use a 60-second or 300-second round window.
- Clock Authority: The
@slasettle/indexerservice provides a synchronized reference clock via/v1/clockto ensure off-chain watchers and frontend status monitors remain aligned.
Health Probing Pipeline
The Go watcher daemon (services/watcher) executes an autonomous pipeline each round:
text
[Round Timer Fires]
|
v
[Duplicate Check Query] ---> has_watcher_voted(sla_id, round_id, watcher)
| (If true, skip round to conserve gas/fees)
v (If false)
[Execute HTTP Health Probe]
| - Target URL from SLA metadata
| - Configurable timeout (default: 5000ms)
| - Validate HTTP 2xx status code
v
[Determine Attestation Status]
| - If 2xx and response within timeout -> CheckStatus::Up (1)
| - If timeout, connection error, or 5xx -> CheckStatus::Down (2)
v
[Hash Target Endpoint]
| - SHA-256 hash of endpoint URL string
v
[Sign & Submit Transaction]
| - submit_check(watcher, sla_id, round_id, endpoint_hash, status)
v
[Stellar Network Confirmation]Check Submission Specification
Watchers invoke submit_check on the watcher_registry contract:
rust
pub fn submit_check(
env: Env,
watcher: Address,
sla_id: u64,
round_id: u64,
endpoint_hash: BytesN<32>,
status: CheckStatus,
) -> Result<(), Error>Parameter Reference
watcher: The public address of the submitting watcher node. Must match transaction signer.sla_id: Identifier of the SLA being evaluated.round_id: Current monitoring round.endpoint_hash: 32-byte cryptographic hash of the probed endpoint. Included in invocation data for auditability.status: Attestation enum (CheckStatus::UporCheckStatus::Down).
Validation Rules
- Contract Active: Rejects with
Error::ContractPausedif the registry is paused. - Authorization: Rejects with
Error::NotAWatcherifwatcheris not present in persistent storage. - Single Vote Enforcement: Rejects with
Error::DuplicateCheckifDataKey::Check(sla_id, round_id, watcher)already exists. Watchers cannot vote twice or modify a submitted vote.
Operational Topology & Redundancy
For production reliability, watcher nodes should be deployed with geographical and infrastructure diversity:
- Distributed across multiple cloud providers (AWS, GCP, Azure) and independent bare-metal servers.
- Spanning multiple geographical regions (North America, Europe, Asia-Pacific) to mitigate regional routing or transit provider outages.
- Running autonomous monitoring loops with local SQLite/in-memory state persistence to prevent duplicate transaction submissions upon daemon restarts.