Consensus
Sylan uses an on‑chain tally of provider‑signed snapshots to decide which response a request should settle on. Nodes don’t vote with arbitrary data—they submit a Provider’s EIP‑712 signature over a compact Snapshot that encodes content + freshness. The chain tallies identical digests and finalizes when a quorum is reached (or after expiry + grace).
This is a conceptual page. Method/event names appear to help you trace behavior, but full ABIs live under Contracts.
Goals
- Correctness: Only Provider‑authorized data can win (EIP‑712 signature check).
- Liveness: Early finalization on quorum, or deferred finalization after expiry.
- Cost: Nodes submit a small, signed summary (hash + timings), not the full payload.
The Snapshot (what gets signed)
Provider signs the following struct off‑chain and hands it to Nodes:
Snapshot {
apiId: bytes32 // logical API identifier
seqNo: uint256 // monotonic per API if enabled
providerTs: uint64 // provider epoch millis
ttl: uint64 // millis; 0 = no TTL (skew check still applies)
contentHash: bytes32 // content address (e.g., IPFS/Merkle root)
}EIP‑712 domain: name = "SylanProviderSnapshot", version = "1".
Freshness checks (on‑chain):
providerTs ≤ nowMs + maxSkewMs(apiId)(reject future‑dated data)- If
ttl ≠ 0, requirenowMs ≤ providerTs + min(ttl, maxTtlMs(apiId))(no stale data)
Signer: the recovered address must equal providerSignerOf(apiId) from AccessRegistry.
Voting & Fork‑choice
When a Node calls submitSnapshot(requestId, s, providerSig, pointerURI):
- Eligibility: caller must be an active Node (if a NodeRegistry is configured).
- One vote per node per request (
already votedguard). - Compute the digest = EIP‑712 hash of
Snapshot. Votes group by digest. - Fork‑choice rules choose the current leader among candidates:
- Higher vote count wins.
- If votes tie → Higher seqNo wins.
- If still tied → Lower providerTs wins (earlier data is preferred).
- Emit
ResponseSubmittedfor traceability; store(node → digest)for slashing/rewards.
Equivocation detection: the first contentHash observed for (apiId, seqNo) is committed. If a later snapshot supplies a different contentHash for the same (apiId, seqNo), emit ProviderEquivocation.
Finalization
A request can finalize on two paths via finalize(requestId):
- Early quorum: if the leader has
votes ≥ quorum, it finalizes immediately. - Deadline path: callable when
nowMs ≥ expiresAtMsandnowMs ≤ expiresAtMs + requestExpiryGraceMs.
Additional checks on finalize:
- API liveness: if the API is no longer active →
RequestFailed(reason = InactiveAPI)and escrow refunds. - Sequence monotonicity (per API setting): if enabled and the winning
seqNois less than the last finalizedseqNo, treat as NoQuorum and fail. This prevents regressions.
Events:
RequestFinalized(requestId, apiId, seqNo, providerTs, contentHash, msgHash, votes)RequestFailed(requestId, apiId, reason)wherereason:1 = NoQuorum2 = InactiveAPI
On success, consensus calls escrow to settle (see Settlement in Request Lifecycle).
Slashing & Rewards (NodeRegistry‑aware)
If a NodeRegistry is configured:
- Nodes whose vote matches the finalized digest are honest; others are mismatched.
- Each mismatched node can be slashed by
slashAmountbps of its current stake. - The total slashed amount is divided equally among honest nodes as a reward (paid from the Node Pool token balance).
- Honest nodes also gain a small reputation increment.
This aligns incentives toward submitting timely, correct snapshots.
Parameters (where they come from)
| Parameter | Scope | Meaning |
|---|---|---|
quorum | Consensus (global) | Identical votes required for early finalization. |
requestExpiryGraceMs | Consensus (global) | Window after expiry during which finalization is still allowed. |
slashAmount (bps) | Consensus (global) | Percentage of stake slashed from mismatching nodes. |
seqMonotonic | AccessRegistry (per API) | Enforce increasing seqNo across finalized requests. |
maxSkewMs | AccessRegistry (per API) | Max future clock skew allowed for providerTs. |
maxTtlMs | AccessRegistry (per API) | Upper cap applied to Snapshot.ttl to bound staleness. |
providerSigner | AccessRegistry (per API) | EOA that must sign the snapshot (EIP‑712). |
Safety notes
- Deterministic request IDs ensure registry/consensus agree on the same request scope.
- Idempotent settlement: calling escrow’s settle methods more than once is safe.
- Pointer URI (
pointerURI) helps indexers link the snapshot to off‑chain artifacts (IPFS, HTTP), but consensus relies only on the hash and signature.
Conceptual flow
What this page intentionally omits
- Contract addresses, ABIs, and function signatures → see Contracts and Architecture → Addresses & ABIs.
- UI code samples → see Quickstart and Integrations.
- Node/Provider operational guides → see Node and Provider sections.