The three-tier boundary
Every property the client handles falls into exactly one of three tiers:- Verified — the client checks it cryptographically or mathematically. If it passes, it is true with overwhelming probability.
- Trusted — the client takes it at face value from a specified source. If the source is wrong, the client is wrong.
- Not trusted — the client never relies on this, no matter who claims it.
Verified
| Property | Mechanism |
|---|---|
| Blob content correctness | BLAKE3 hash tree verification on every chunk |
| Voucher signatures | EIP-712 + SignatureChecker.isValidSignatureNow |
NodeInfo binding (NodeId ↔ Ethereum address) | EIP-712 binding signature + ed25519 ownership proof recorded on-chain |
| Channel settlement amount | On-chain contract enforces voucher signature + deposit cap |
| Manifest integrity | Manifest blob’s own BLAKE3 hash is the file ID; chunks are individually hash-verified |
| Protocol message authenticity | ed25519 wire signatures (and slash_sig for slash-relevant messages) |
Trusted
These are safe in a working, honest infrastructure — but they depend on something outside the client’s direct verification.| Property | Trusted source |
|---|---|
| ”These nodes exist” | Your L2 RPC provider’s response to StakingRegistry.getNodes() |
| ”This blob hash corresponds to the file I want” | Whoever told you the hash (the content provider’s UI, a manifest, a friend) |
| “Clocks are roughly synchronized” | NTP |
| ”Gossip messages are reasonably fresh” | NTP + signed timestamps (±60 s for NodeAnnounce, ±1 h for reputation reports) |
| “The app server I’m authenticating to is the real one” | Your content provider’s out-of-band identity (NodeId fingerprint, DNS) |
| “Relays I route through are content-blind” | QUIC encryption; structural property of iroh relays |
Specific trust assumptions worth calling out
- L2 RPC provider honesty. A malicious RPC could hide
ChannelCloseInitiatedevents from your dispute monitor, or return a fabricated node list to eclipse you. Mitigation: multi-source bootstrap (on-chain registry + DNS seed list + optional operator static list, 2-of-3 agreement) and multiple independent RPC providers. - App server custody of
K_blob. For encrypted content, the content provider’s app server holds the plaintext blob key. Compromise of the app server exposes all that provider’s content. Per-provider, not protocol-wide. - NTP correctness. Clock skew breaks gossip freshness checks and voucher replay windows. Skewed attacker + skewed victim is how certain attacks attempt to slip vouchers or fake freshness. Mitigation: generous windows absorb typical NTP jitter; gross skew is self-detecting.
Not trusted
Things you must never accept without cryptographic verification:| Property | Why not |
|---|---|
| ”The bytes I received are what you requested” | Verify the BLAKE3 hash. Do not assume by URL, NodeId, or prior trust. |
| ”The rate I charged you is what I advertised” | Slash-able offense if lied. Don’t accept charges above the advertised rate. |
”I have this blob” (claim in ProbeResponse) | Slash-able if wrong — but client must still verify on delivery. |
| ”I am this NodeId” (over the wire) | Verify the ed25519 signature. iroh QUIC does this at handshake. |
| Cross-region announcements | A node advertising “I’m in DE” without actually being in DE leaks to the network — your score computation uses measured RTT, not claimed region. |
| Redirects to URLs | Redirects are only NodeId. A peer that sends you a URL is out of protocol. |
How this plays in practice
A client fetch pipeline, tier by tier:- Hash comes from the content provider (trusted — they told you what you want).
- Node list comes from the registry (trusted — your RPC returned it).
- NodeId↔Ethereum binding is verified — on-chain registry + EIP-712 + ed25519 proof.
- Probe response is verified (wire sig) but its
has_blob: trueclaim is trusted provisionally — confirmed only by actual delivery. - Streamed bytes are verified — BLAKE3 leaf-by-leaf. No trust.
- Voucher signature from you is verified on-chain by the contract — no one trusts it without signature.
- Settlement is verified on-chain — the contract enforces correctness.
When to be paranoid
- You’re downloading high-value or sensitive content. Consider tightening the multi-source bootstrap policy (require 3-of-3 agreement instead of the default 2-of-3) and pinning the registry RPC to a provider you operate.
- You’re downloading over hostile networks. Tighten voucher cadence (smaller = tighter bound on unpaid-delivery loss).
- You’re automating downloads without human supervision. Set a hard
--max-budget-usdcper fetch to bound worst-case spend. - You’re running multiple client identities. Rotate NodeIds aggressively to break linkability.
What this trust model explicitly does not give you
- Anonymity from on-path observers. QUIC metadata, IP addresses, and timing are visible. This is an accountability-first design.
- Forward secrecy for previously-delivered encrypted content. App server
K_blobcompromise decrypts historical ciphertexts. - Protection from a compromised endpoint (your own device). Device-level compromise exposes plaintext, your keys, and your session tokens. All standard device hardening applies.