diff --git a/docs/audiences/troubleshooting.md b/docs/audiences/troubleshooting.md index b8913df..4f3262a 100644 --- a/docs/audiences/troubleshooting.md +++ b/docs/audiences/troubleshooting.md @@ -44,6 +44,12 @@ Connect, re-auth, a declined request, and watch-only sessions that can't sign. → [Wallet session can't sign](../support/troubleshooting.md#wallet-session) +## Node & extension issues + +The browser extension shows your node as offline even though it's running and healthy. + +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) + ## Pre-flight & cost checks — don't waste a capsule `digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). diff --git a/docs/protocol/peer-network.md b/docs/protocol/peer-network.md index 58d6102..ef198ec 100644 --- a/docs/protocol/peer-network.md +++ b/docs/protocol/peer-network.md @@ -160,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. diff --git a/docs/support/troubleshooting.md b/docs/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/docs/support/troubleshooting.md +++ b/docs/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/de/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/de/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index e132acc..4f3262a 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Jeder Fehler liefert dir einen stabilen Code und eine request-id, die direkt zum Server-Log führt, On-Chain-Spends sind race-guarded, sodass du nie doppelt zahlst, und klare Pre-Flight-Guards verhindern verschwendete capsules, bevor du $DIG ausgibst." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> Jeder Fehler liefert dir einen **stabilen Code** und eine **request-id**, die direkt zum Server-Log führt, On-Chain-Spends sind **race-guarded**, sodass du nie doppelt zahlst, und klare **Pre-Flight-Guards** verhindern verschwendete capsules, bevor du $DIG ausgibst. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Das Denkmodell — finde deinen Fehler anhand seines Codes {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Jede Oberfläche — die dig RPC, die digstore-CLI, DIGHUb, der `chia://`-Loader, das SDK — bildet einen Fehler auf einen **STABILEN Code** ab. **Verzweige anhand des Codes, niemals anhand der Meldung.** Ein konsolidierter Katalog deckt sie alle ab und wird auch maschinenlesbar veröffentlicht. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Pre-Flight-Guards (`digstore doctor`, `--dry-run`, `--if-changed`) und fortsetzbare Anker sorgen dafür, dass eine hängende oder wirkungslose Veröffentlichung **niemals stillschweigend Geld ausgibt**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Häufige Veröffentlichungsfehler {#common-publishing-failures} +## Common publishing failures -Unzureichende Mittel, ein Bestätigungs-Timeout (fortsetzbar — dein Spend geht nicht verloren) und das Non-Fast-Forward „remote root has advanced". +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". → [Troubleshooting](../support/troubleshooting.md) -## Lese- & Verifizierungsfehler {#read--verify-failures} +## Read & verify failures -Proof-Mismatch, Entschlüsselungs-/Salt-Fehler und Not-Found-/Decoy-Antworten. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Lese- & Verifizierungsfehler](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Wallet- & Session-Probleme {#wallet--session-issues} +## Wallet & session issues -Verbindung, Re-Authentifizierung, eine abgelehnte Anfrage und Watch-Only-Sessions, die nicht signieren können. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [Wallet-Session kann nicht signieren](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Pre-Flight- & Kostenprüfungen — keine capsule verschwenden {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (Umgebung + Bereitschaft), `--dry-run` (Vorschau der Kosten und der voraussichtlichen capsule) und `--if-changed` (ein bytegleicher Build ist ein No-Op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Deploy aus GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-Chain-Anchoring → Kosten & Sicherheit](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Referenz der Fehlercodes {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI-Exit-Codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — eine konsolidierte Tabelle. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Fehlercodes](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -Kosten, die kostenlose Testphase, warum der Preis einheitlich ist, wo man $DIG bekommt, und „gibt es ein Testnet?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## Hilfe bekommen {#get-help} +## Get help -Discord + GitHub, und wie man einen guten Bericht einreicht — **niemals Geheimnisse einfügen**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [Hilfe bekommen](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Status & Changelog {#status--changelog} +## Status & changelog → [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Tiefer einsteigen: das Protokoll {#go-deeper-the-protocol} +## Go deeper: the protocol -- **Lese- & Verifizierungsfehler** → [Proofs & Sicherheit](../digstore/format/proofs-and-security.md) · [URNs & Verschlüsselung](../digstore/format/urns-and-encryption.md) -- **RPC-`-32xxx`-Codes** → [die dig-RPC-Methoden](../rpc/methods.md) · [Konformität](../rpc/conformance.md) -- **Alles** → [Protokoll-Deep-Dive](../protocol-deep-dive.md) · [Konzepte & Glossar](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/de/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/de/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/es/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/es/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index bb7fe49..4f3262a 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Cada fallo te da un código estable y un request-id que enlaza directamente con el log del servidor, los gastos en cadena están protegidos contra condiciones de carrera para que nunca pagues dos veces, y verificaciones previas claras evitan capsules desperdiciados antes de gastar $DIG." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> Cada fallo te da un **código estable** y un **request-id** que enlaza directamente con el log del servidor, los gastos en cadena están **protegidos contra condiciones de carrera** para que nunca pagues dos veces, y verificaciones previas claras evitan capsules desperdiciados antes de gastar $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## El modelo mental — encuentra tu fallo por su código {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Cada superficie — el dig RPC, la CLI de digstore, DIGHUb, el loader `chia://`, el SDK — asigna un fallo a un **código ESTABLE**. **Ramifica según el código, nunca según el mensaje.** Un catálogo consolidado los cubre todos y también se publica en formato legible por máquinas. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Las verificaciones previas (`digstore doctor`, `--dry-run`, `--if-changed`) y los anclajes reanudables significan que una publicación atascada o sin efecto **nunca gasta silenciosamente**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Fallos comunes de publicación {#common-publishing-failures} +## Common publishing failures -Fondos insuficientes, un tiempo de espera de confirmación agotado (reanudable — tu gasto no se pierde), y el "la raíz remota ha avanzado" de no-fast-forward. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Resolución de problemas](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Fallos de lectura y verificación {#read--verify-failures} +## Read & verify failures -Discrepancia de pruebas, errores de descifrado/salt, y respuestas de no-encontrado / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Fallos de lectura y verificación](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Problemas de wallet y sesión {#wallet--session-issues} +## Wallet & session issues -Conexión, reautenticación, una solicitud rechazada, y sesiones de solo lectura que no pueden firmar. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [La sesión de wallet no puede firmar](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Verificaciones previas y de costo — no desperdicies un capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (entorno + preparación), `--dry-run` (previsualiza el costo y el capsule que se generaría), y `--if-changed` (una build idéntica byte a byte es un no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Deploy desde GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [Anclaje en cadena → costo y seguridad](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Referencia de códigos de error {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Códigos de salida de la CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — una tabla consolidada. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Códigos de error](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## Preguntas frecuentes {#faq} +## Error codes reference -Costo, la prueba gratuita, por qué el precio es uniforme, dónde conseguir $DIG, y "¿hay una testnet?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. -→ [Preguntas frecuentes](../support/faq.md) +→ [Error codes](../support/error-codes.md) -## Obtener ayuda {#get-help} +## FAQ -Discord + GitHub, y cómo presentar un buen reporte — **nunca pegues secretos**. +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". -→ [Obtener ayuda](../support/get-help.md) +→ [FAQ](../support/faq.md) -## Estado y changelog {#status--changelog} +## Get help -→ [Estado](../support/status.md) · [Changelog](../support/changelog.md) +Discord + GitHub, and how to file a good report — **never paste secrets**. + +→ [Get help](../support/get-help.md) + +## Status & changelog + +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Profundiza: el protocolo {#go-deeper-the-protocol} +## Go deeper: the protocol -- **fallos de lectura y verificación** → [Pruebas y seguridad](../digstore/format/proofs-and-security.md) · [URNs y cifrado](../digstore/format/urns-and-encryption.md) -- **códigos `-32xxx` de RPC** → [los métodos del dig RPC](../rpc/methods.md) · [Conformidad](../rpc/conformance.md) -- **Todo** → [Inmersión profunda en el protocolo](../protocol-deep-dive.md) · [Conceptos y glosario](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/es/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/es/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/fr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 21bf290..4f3262a 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Chaque échec vous donne un code stable et un request-id qui renvoie directement au journal du serveur, les dépenses on-chain sont protégées contre les courses pour que vous ne payiez jamais deux fois, et des garde-fous de pré-vérification clairs évitent de gaspiller des capsules avant de dépenser du $DIG." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Dépannage {#troubleshooting} +# Troubleshooting -> Chaque échec vous donne un **code stable** et un **request-id** qui renvoie directement au journal du serveur, les dépenses on-chain sont **protégées contre les courses** pour que vous ne payiez jamais deux fois, et des **garde-fous de pré-vérification** clairs évitent de gaspiller des capsules avant de dépenser du $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Le modèle mental — retrouvez votre échec par son code {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Chaque surface — le dig RPC, la CLI digstore, DIGHUb, le chargeur `chia://`, le SDK — associe un échec à un **code STABLE**. **Aiguillez sur le code, jamais sur le message.** Un catalogue consolidé unique les couvre tous et est aussi publié de façon lisible par machine. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Les garde-fous de pré-vérification (`digstore doctor`, `--dry-run`, `--if-changed`) et les ancrages reprenables signifient qu'une publication bloquée ou sans effet **ne dépense jamais silencieusement**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Échecs de publication courants {#common-publishing-failures} +## Common publishing failures -Fonds insuffisants, un délai de confirmation dépassé (reprenable — votre dépense n'est pas perdue), et la « racine distante a avancé » en non-fast-forward. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Dépannage](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Échecs de lecture et de vérification {#read--verify-failures} +## Read & verify failures -Incompatibilité de preuve, erreurs de déchiffrement/sel, et réponses introuvable / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Échecs de lecture et de vérification](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Problèmes de portefeuille et de session {#wallet--session-issues} +## Wallet & session issues -Connexion, ré-authentification, une requête refusée, et les sessions en lecture seule qui ne peuvent pas signer. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [La session du portefeuille ne peut pas signer](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Vérifications de pré-vérification et de coût — ne gaspillez pas une capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (environnement + préparation), `--dry-run` (prévisualiser le coût et la capsule potentielle), et `--if-changed` (un build identique à l'octet près est un no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Déployer depuis GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [Ancrage on-chain → coût et sécurité](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Référence des codes d'erreur {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Codes de sortie CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — un tableau consolidé unique. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Codes d'erreur](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -Coût, l'essai gratuit, pourquoi le prix est uniforme, où obtenir du $DIG, et « y a-t-il un testnet ? ». +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## Obtenir de l'aide {#get-help} +## Get help -Discord + GitHub, et comment déposer un bon rapport — **ne collez jamais de secrets**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [Obtenir de l'aide](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Statut et journal des modifications {#status--changelog} +## Status & changelog -→ [Statut](../support/status.md) · [Journal des modifications](../support/changelog.md) +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Aller plus loin : le protocole {#go-deeper-the-protocol} +## Go deeper: the protocol -- **échecs de lecture et de vérification** → [Preuves et sécurité](../digstore/format/proofs-and-security.md) · [URN et chiffrement](../digstore/format/urns-and-encryption.md) -- **codes RPC `-32xxx`** → [les méthodes du dig RPC](../rpc/methods.md) · [Conformité](../rpc/conformance.md) -- **Tout** → [Plongée en profondeur dans le protocole](../protocol-deep-dive.md) · [Concepts et glossaire](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/fr/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/hi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/hi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index bd6ee21..4f3262a 100644 --- a/i18n/hi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/hi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "हर विफलता आपको एक स्थिर कोड और एक request-id देती है जो सीधे सर्वर लॉग से जुड़ती है, ऑन-चेन spends रेस-गार्डेड हैं ताकि आप कभी दोगुना भुगतान न करें, और स्पष्ट pre-flight गार्ड्स $DIG खर्च करने से पहले बर्बाद capsules को रोकते हैं।" +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> हर विफलता आपको एक **स्थिर कोड** और एक **request-id** देती है जो सीधे सर्वर लॉग से जुड़ती है, ऑन-चेन spends **रेस-गार्डेड** हैं ताकि आप कभी दोगुना भुगतान न करें, और स्पष्ट **pre-flight गार्ड्स** $DIG खर्च करने से पहले बर्बाद capsules को रोकते हैं। +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## मेंटल मॉडल — अपनी विफलता को उसके कोड से खोजें {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -हर सतह — dig RPC, digstore CLI, DIGHUb, `chia://` loader, SDK — एक विफलता को एक **स्थिर कोड** से मैप करती है। **कोड पर branch करें, कभी मैसेज पर नहीं।** एक समेकित कैटलॉग इन सभी को कवर करता है और मशीन-रीडेबल रूप में भी पब्लिश होता है। +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Pre-flight गार्ड्स (`digstore doctor`, `--dry-run`, `--if-changed`) और resumable anchors का मतलब है कि एक अटका हुआ या no-op publish **कभी चुपचाप खर्च नहीं करता**। +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## सामान्य publishing विफलताएं {#common-publishing-failures} +## Common publishing failures -अपर्याप्त फंड, एक confirm टाइमआउट (resumable — आपका spend खोया नहीं है), और non-fast-forward "remote root has advanced"। +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". → [Troubleshooting](../support/troubleshooting.md) -## Read और verify विफलताएं {#read--verify-failures} +## Read & verify failures -Proof मिसमैच, decrypt/salt एरर्स, और not-found / decoy responses। +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. → [Read & verify failures](../support/troubleshooting.md#verification-failed) -## वॉलेट और सेशन समस्याएं {#wallet--session-issues} +## Wallet & session issues -Connect, re-auth, एक अस्वीकृत रिक्वेस्ट, और watch-only सेशन्स जो साइन नहीं कर सकते। +Connect, re-auth, a declined request, and watch-only sessions that can't sign. → [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Pre-flight और लागत जांच — एक capsule बर्बाद न करें {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (environment + तैयारी), `--dry-run` (लागत और होने वाले capsule का पूर्वावलोकन), और `--if-changed` (एक byte-identical बिल्ड एक no-op है)। +The browser extension shows your node as offline even though it's running and healthy. + +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) + +## Pre-flight & cost checks — don't waste a capsule + +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). → [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## एरर कोड्स संदर्भ {#error-codes-reference} +## Error codes reference -CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — एक समेकित तालिका। +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. → [Error codes](../support/error-codes.md) -## FAQ {#faq} +## FAQ -लागत, फ्री ट्रायल, कीमत यूनिफॉर्म क्यों है, $DIG कहां पाएं, और "क्या कोई testnet है?"। +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## मदद पाएं {#get-help} +## Get help -Discord + GitHub, और एक अच्छी रिपोर्ट कैसे फाइल करें — **कभी सीक्रेट्स पेस्ट न करें**। +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [मदद पाएं](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Status और changelog {#status--changelog} +## Status & changelog → [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## गहराई में जाएं: प्रोटोकॉल {#go-deeper-the-protocol} +## Go deeper: the protocol -- **read और verify विफलताएं** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) -- **RPC `-32xxx` कोड्स** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) -- **सब कुछ** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/hi/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/hi/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/hi/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/hi/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/id/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/id/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 6321333..4f3262a 100644 --- a/i18n/id/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/id/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Setiap kegagalan memberi Anda sebuah kode stabil dan sebuah request-id yang langsung terhubung ke log server, spend on-chain dijaga terhadap race-condition sehingga Anda tak pernah membayar dua kali, dan pemeriksaan pre-flight yang jelas mencegah capsule sia-sia sebelum Anda mengeluarkan $DIG." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> Setiap kegagalan memberi Anda sebuah **kode stabil** dan sebuah **request-id** yang langsung terhubung ke log server, spend on-chain **dijaga terhadap race-condition** sehingga Anda tak pernah membayar dua kali, dan pemeriksaan **pre-flight** yang jelas mencegah capsule sia-sia sebelum Anda mengeluarkan $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Model mental — temukan kegagalan Anda lewat kodenya {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Setiap permukaan — dig RPC, CLI digstore, DIGHUb, loader `chia://`, SDK — memetakan sebuah kegagalan ke satu **kode STABIL**. **Bercabang pada kodenya, jangan pernah pada pesannya.** Satu katalog konsolidasi mencakup semuanya dan juga diterbitkan dalam bentuk machine-readable. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Pemeriksaan pre-flight (`digstore doctor`, `--dry-run`, `--if-changed`) dan anchor yang dapat dilanjutkan (resumable) berarti sebuah publish yang macet atau no-op **tidak pernah diam-diam mengeluarkan biaya**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Kegagalan publish yang umum {#common-publishing-failures} +## Common publishing failures -Dana tidak cukup, timeout konfirmasi (dapat dilanjutkan — spend Anda tidak hilang), dan "root remote telah maju" yang non-fast-forward. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". → [Troubleshooting](../support/troubleshooting.md) -## Kegagalan baca & verifikasi {#read--verify-failures} +## Read & verify failures -Ketidakcocokan proof, error dekripsi/salt, dan respons not-found / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Kegagalan baca & verifikasi](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Masalah wallet & sesi {#wallet--session-issues} +## Wallet & session issues -Koneksi, re-autentikasi, permintaan yang ditolak, dan sesi watch-only yang tidak bisa menandatangani. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [Sesi wallet tidak bisa menandatangani](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Pemeriksaan pre-flight & biaya — jangan sia-siakan sebuah capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (lingkungan + kesiapan), `--dry-run` (preview biaya dan capsule yang akan dihasilkan), dan `--if-changed` (build yang identik secara byte adalah no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Deploy dari GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [Anchoring on-chain → biaya & keamanan](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Referensi kode error {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Kode exit CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — satu tabel konsolidasi. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Kode error](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -Biaya, uji coba gratis, alasan harga bersifat seragam, cara mendapatkan $DIG, dan "apakah ada testnet?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## Dapatkan bantuan {#get-help} +## Get help -Discord + GitHub, dan cara melaporkan masalah dengan baik — **jangan pernah menempel rahasia**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [Dapatkan bantuan](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Status & changelog {#status--changelog} +## Status & changelog → [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Mendalami lebih jauh: protokolnya {#go-deeper-the-protocol} +## Go deeper: the protocol -- **kegagalan baca & verifikasi** → [Proof & keamanan](../digstore/format/proofs-and-security.md) · [URN & enkripsi](../digstore/format/urns-and-encryption.md) -- **kode RPC `-32xxx`** → [metode dig RPC](../rpc/methods.md) · [Konformansi](../rpc/conformance.md) -- **Semuanya** → [Pembahasan mendalam protokol](../protocol-deep-dive.md) · [Konsep & glosarium](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/id/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/id/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/id/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/id/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/ja/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 4f4b053..4f3262a 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 -title: トラブルシューティング — 問題を解決する -description: "すべての失敗はサーバーログに直接結びつく安定したコードとrequest-idを提供し、オンチェーンの支出は競合制御されているため二重支払いは決して起こらず、明確な事前チェックによって$DIGを使う前に無駄なcapsuleの発生を防ぎます。" +title: Troubleshooting — get unstuck +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# トラブルシューティング {#troubleshooting} +# Troubleshooting -> すべての失敗は、サーバーログに直接結びつく**安定したコード**と**request-id**を提供し、オンチェーンの支出は**競合制御されている**ため二重支払いは決して起こらず、明確な**事前チェック**が$DIGを使う前に無駄なcapsuleの発生を防ぎます。 +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## メンタルモデル — コードで失敗を特定する {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -dig RPC、digstore CLI、DIGHUb、`chia://`ローダー、SDKといったすべての面が、失敗を1つの**安定したコード**に対応付けます。**コードで分岐し、メッセージでは分岐しないでください。** 1つに統合されたカタログがそれらすべてをカバーし、機械可読な形でも公開されています。 +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -事前チェック(`digstore doctor`、`--dry-run`、`--if-changed`)と再開可能なアンカーにより、行き詰まった、あるいは何も変わらない公開が**サイレントに支出を発生させる**ことは決してありません。 +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## よくある公開の失敗 {#common-publishing-failures} +## Common publishing failures -資金不足、確定タイムアウト(再開可能であり、あなたの支出が失われることはありません)、そして早送りできない「リモートのrootが進んでいます」というエラー。 +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [トラブルシューティング](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## 読み取りと検証の失敗 {#read--verify-failures} +## Read & verify failures -証明の不一致、復号/saltのエラー、見つからない/デコイ応答。 +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [読み取りと検証の失敗](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## ウォレットとセッションの問題 {#wallet--session-issues} +## Wallet & session issues -接続、再認証、拒否されたリクエスト、署名できない閲覧専用セッション。 +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [ウォレットセッションが署名できない](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## 事前チェックと費用の確認 — capsuleを無駄にしない {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor`(環境と準備状況の確認)、`--dry-run`(費用と作成予定のcapsuleをプレビュー)、`--if-changed`(バイト単位で同一のビルドは何もしません)。 +The browser extension shows your node as offline even though it's running and healthy. -→ [GitHub Actionsからデプロイする](../digstore/cli/deploy-from-github-actions.md) · [オンチェーンアンカリング → 費用と安全性](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## エラーコードリファレンス {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI終了コード・RPCの`-32xxx`・DIGHUb・digローダー・SDK — 1つに統合された表です。 +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [エラーコード](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -費用、無料トライアル、価格が均一である理由、$DIGの入手先、「テストネットはありますか?」について。 +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## ヘルプを得る {#get-help} +## Get help -DiscordとGitHub、そして良い報告の書き方 — **決して秘密情報を貼り付けないでください**。 +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [ヘルプを得る](../support/get-help.md) +→ [Get help](../support/get-help.md) -## ステータスと変更履歴 {#status--changelog} +## Status & changelog -→ [ステータス](../support/status.md) · [変更履歴](../support/changelog.md) +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## さらに深く:プロトコル {#go-deeper-the-protocol} +## Go deeper: the protocol -- **読み取りと検証の失敗** → [証明とセキュリティ](../digstore/format/proofs-and-security.md) · [URNと暗号化](../digstore/format/urns-and-encryption.md) -- **RPCの`-32xxx`コード** → [dig RPCメソッド](../rpc/methods.md) · [準拠性](../rpc/conformance.md) -- **すべて** → [プロトコル詳解](../protocol-deep-dive.md) · [概念と用語集](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/ja/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/ko/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index c3f3634..4f3262a 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "모든 실패는 서버 로그와 직접 연결되는 안정적인 코드와 request-id를 제공하며, 온체인 스펜드는 이중 지불을 방지하도록 경쟁 조건이 방지되어 있고, 명확한 사전 점검 가드가 $DIG를 쓰기 전에 낭비되는 capsule을 막아줍니다." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> 모든 실패는 서버 로그와 직접 연결되는 **안정적인 코드**와 **request-id**를 제공하며, 온체인 스펜드는 **경쟁 조건이 방지**되어 있어 절대 이중 지불이 발생하지 않고, 명확한 **사전 점검 가드**가 $DIG를 쓰기 전에 낭비되는 capsule을 막아줍니다. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## 사고 모델 — 코드로 실패를 찾아내기 {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -dig RPC, digstore CLI, DIGHUb, `chia://` 로더, SDK 등 모든 표면은 실패를 하나의 **안정적인(STABLE) 코드**로 매핑합니다. **메시지가 아니라 항상 코드로 분기하세요.** 하나의 통합 카탈로그가 이 모든 것을 다루며, 기계가 읽을 수 있는 형식으로도 공개되어 있습니다. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -사전 점검 가드(`digstore doctor`, `--dry-run`, `--if-changed`)와 재개 가능한 앵커 덕분에, 멈추거나 아무 변화가 없는 게시 작업이 **조용히 비용을 지불하는 일은 절대 없습니다**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## 흔한 게시 실패 {#common-publishing-failures} +## Common publishing failures -잔액 부족, 컨펌 타임아웃(재개 가능 — 스펜드가 사라지지 않음), 그리고 "remote root has advanced"라는 non-fast-forward 오류. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". → [Troubleshooting](../support/troubleshooting.md) -## 읽기 및 검증 실패 {#read--verify-failures} +## Read & verify failures -증명 불일치, 복호화/salt 오류, not-found / decoy 응답. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [읽기 및 검증 실패](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## 지갑 및 세션 문제 {#wallet--session-issues} +## Wallet & session issues -연결, 재인증, 거부된 요청, 서명할 수 없는 조회 전용(watch-only) 세션. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [지갑 세션이 서명할 수 없음](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## 사전 점검 및 비용 확인 — capsule을 낭비하지 마세요 {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor`(환경 및 준비 상태 확인), `--dry-run`(비용과 생성될 capsule을 미리보기), `--if-changed`(바이트 단위로 동일한 빌드는 아무 작업도 하지 않음). +The browser extension shows your node as offline even though it's running and healthy. -→ [GitHub Actions에서 배포하기](../digstore/cli/deploy-from-github-actions.md) · [온체인 앵커링 → 비용과 안전성](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## 오류 코드 레퍼런스 {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI 종료 코드 · RPC `-32xxx` · DIGHUb · dig-loader · SDK — 하나의 통합 표. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [오류 코드](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -비용, 무료 체험, 가격이 균일한 이유, $DIG를 얻는 방법, 그리고 "테스트넷이 있나요?" 등. +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## 도움 받기 {#get-help} +## Get help -Discord와 GitHub, 그리고 좋은 리포트를 작성하는 방법 — **절대 비밀 정보를 붙여넣지 마세요**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [도움 받기](../support/get-help.md) +→ [Get help](../support/get-help.md) -## 상태 및 변경 내역 {#status--changelog} +## Status & changelog -→ [상태](../support/status.md) · [변경 내역](../support/changelog.md) +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## 더 깊이 알아보기: 프로토콜 {#go-deeper-the-protocol} +## Go deeper: the protocol -- **읽기 및 검증 실패** → [증명과 보안](../digstore/format/proofs-and-security.md) · [URN과 암호화](../digstore/format/urns-and-encryption.md) -- **RPC `-32xxx` 코드** → [dig RPC 메서드](../rpc/methods.md) · [적합성](../rpc/conformance.md) -- **모든 것** → [프로토콜 심층 분석](../protocol-deep-dive.md) · [개념 및 용어집](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/ko/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 6fc14d5..4f3262a 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Toda falha te dá um código estável e um request-id que se conecta diretamente ao log do servidor, os gastos on-chain são protegidos contra race conditions para que você nunca pague em duplicidade, e proteções pré-voo claras evitam capsules desperdiçados antes de você gastar $DIG." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> Toda falha te dá um **código estável** e um **request-id** que se conecta diretamente ao log do servidor, os gastos on-chain são **protegidos contra race conditions** para que você nunca pague em duplicidade, e proteções **pré-voo** claras evitam capsules desperdiçados antes de você gastar $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## O modelo mental — encontre sua falha pelo código {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Toda superfície — o dig RPC, a CLI digstore, a DIGHUb, o loader `chia://`, o SDK — mapeia uma falha para um **código ESTÁVEL**. **Faça branch pelo código, nunca pela mensagem.** Um catálogo consolidado cobre todos eles e também é publicado de forma legível por máquina. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Proteções pré-voo (`digstore doctor`, `--dry-run`, `--if-changed`) e âncoras retomáveis significam que uma publicação travada ou sem efeito **nunca gasta silenciosamente**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Falhas comuns de publicação {#common-publishing-failures} +## Common publishing failures -Fundos insuficientes, um timeout de confirmação (retomável — seu gasto não é perdido), e o "a raiz remota avançou" de não-fast-forward. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Solução de problemas](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Falhas de leitura e verificação {#read--verify-failures} +## Read & verify failures -Incompatibilidade de prova, erros de descriptografia/salt, e respostas de não encontrado / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Falhas de leitura e verificação](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Problemas de carteira e sessão {#wallet--session-issues} +## Wallet & session issues -Conexão, reautenticação, uma requisição recusada, e sessões somente-leitura que não podem assinar. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [A sessão da carteira não consegue assinar](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Checagens pré-voo e de custo — não desperdice um capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (ambiente + prontidão), `--dry-run` (pré-visualize o custo e o capsule que seria criado), e `--if-changed` (um build byte-a-byte idêntico é um no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Deploy a partir do GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [Ancoragem on-chain → custo e segurança](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Referência de códigos de erro {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Códigos de saída da CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — uma tabela consolidada. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Códigos de erro](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -Custo, o teste gratuito, por que o preço é uniforme, onde conseguir $DIG, e "existe uma testnet?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## Obtenha ajuda {#get-help} +## Get help -Discord + GitHub, e como registrar um bom relatório — **nunca cole segredos**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [Obtenha ajuda](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Status e changelog {#status--changelog} +## Status & changelog → [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Aprofunde-se: o protocolo {#go-deeper-the-protocol} +## Go deeper: the protocol -- **falhas de leitura e verificação** → [Provas e segurança](../digstore/format/proofs-and-security.md) · [URNs e criptografia](../digstore/format/urns-and-encryption.md) -- **códigos `-32xxx` do RPC** → [os métodos do dig RPC](../rpc/methods.md) · [Conformidade](../rpc/conformance.md) -- **Tudo** → [Aprofundamento no protocolo](../protocol-deep-dive.md) · [Conceitos e glossário](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/ru/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 231a487..4f3262a 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "Каждый сбой даёт вам стабильный код и request-id, напрямую связанный с логом сервера, on-chain траты защищены от гонок, так что вы никогда не заплатите дважды, а понятные предварительные проверки останавливают напрасные capsule до того, как вы потратите $DIG." +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Troubleshooting {#troubleshooting} +# Troubleshooting -> Каждый сбой даёт вам **стабильный код** и **request-id**, напрямую связанный с логом сервера, on-chain траты **защищены от гонок**, так что вы никогда не заплатите дважды, а понятные **предварительные проверки** останавливают напрасные capsule до того, как вы потратите $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Ментальная модель — находите свой сбой по его коду {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Каждая поверхность — dig RPC, CLI digstore, DIGHUb, загрузчик `chia://`, SDK — сопоставляет сбой с одним **СТАБИЛЬНЫМ кодом**. **Ветвитесь по коду, никогда по тексту сообщения.** Единый сводный каталог охватывает их все и также публикуется в машиночитаемом виде. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Предварительные проверки (`digstore doctor`, `--dry-run`, `--if-changed`) и возобновляемые закрепления означают, что застрявшая или холостая публикация **никогда не тратит средства втихую**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Частые сбои публикации {#common-publishing-failures} +## Common publishing failures -Недостаток средств, таймаут подтверждения (возобновляемый — ваша трата не потеряна) и non-fast-forward «удалённый корень продвинулся вперёд». +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Устранение неполадок](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Сбои чтения и верификации {#read--verify-failures} +## Read & verify failures -Несовпадение доказательства, ошибки расшифровки/соли и ответы «не найдено» / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Сбои чтения и верификации](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Проблемы с кошельком и сессией {#wallet--session-issues} +## Wallet & session issues -Подключение, повторная аутентификация, отклонённый запрос и сессии только для чтения, которые не могут подписывать. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [Сессия кошелька не может подписывать](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Предварительные проверки и проверки стоимости — не тратьте capsule впустую {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (окружение + готовность), `--dry-run` (предпросмотр стоимости и предполагаемой capsule) и `--if-changed` (байт-идентичная сборка становится no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Деплой из GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain закрепление → стоимость и безопасность](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Справочник кодов ошибок {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Коды выхода CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — одна сводная таблица. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Коды ошибок](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## FAQ {#faq} +## Error codes reference -Стоимость, бесплатный пробный период, почему цена единая, где взять $DIG и «есть ли тестовая сеть?». +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. + +→ [Error codes](../support/error-codes.md) + +## FAQ + +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". → [FAQ](../support/faq.md) -## Получить помощь {#get-help} +## Get help -Discord + GitHub, и как составить хороший отчёт об ошибке — **никогда не вставляйте секреты**. +Discord + GitHub, and how to file a good report — **never paste secrets**. -→ [Получить помощь](../support/get-help.md) +→ [Get help](../support/get-help.md) -## Статус и список изменений {#status--changelog} +## Status & changelog -→ [Статус](../support/status.md) · [Список изменений](../support/changelog.md) +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Углубитесь: протокол {#go-deeper-the-protocol} +## Go deeper: the protocol -- **сбои чтения и верификации** → [Доказательства и безопасность](../digstore/format/proofs-and-security.md) · [URN и шифрование](../digstore/format/urns-and-encryption.md) -- **коды RPC `-32xxx`** → [методы dig RPC](../rpc/methods.md) · [Соответствие](../rpc/conformance.md) -- **Всё сразу** → [Глубокое погружение в протокол](../protocol-deep-dive.md) · [Концепции и глоссарий](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/ru/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/tr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/tr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 5fc2ca3..4f3262a 100644 --- a/i18n/tr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/tr/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 -title: Sorun giderme — takılmayı aşın -description: "Her hata, sunucu günlüğüne doğrudan bağlanan kararlı bir kod ve bir istek kimliği verir, zincir üzeri harcamalar asla iki kez ödeme yapmamanız için yarış korumalıdır ve net ön uçuş korumaları $DIG harcamadan önce boşa giden capsule'leri durdurur." +title: Troubleshooting — get unstuck +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Sorun giderme {#troubleshooting} +# Troubleshooting -> Her hata, sunucu günlüğüne doğrudan bağlanan bir **kararlı kod** ve bir **istek kimliği** verir, zincir üzeri harcamalar asla iki kez ödeme yapmamanız için **yarış korumalıdır** ve net **ön uçuş korumaları**, $DIG harcamadan önce boşa giden capsule'leri durdurur. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Zihinsel model — hatanızı koduyla bulun {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Her yüzey — dig RPC, digstore CLI, DIGHUb, `chia://` yükleyicisi, SDK — bir hatayı tek bir **KARARLI koda** eşler. **Kodda dallanın, asla mesajda değil.** Tek bir birleştirilmiş katalog hepsini kapsar ve ayrıca makine tarafından okunabilir olarak yayınlanır. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Ön uçuş korumaları (`digstore doctor`, `--dry-run`, `--if-changed`) ve devam ettirilebilir sabitlemeler, takılan veya hiçbir işlem yapmayan bir yayınlamanın **asla sessizce harcama yapmaması** anlamına gelir. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Yaygın yayınlama hataları {#common-publishing-failures} +## Common publishing failures -Yetersiz fon, bir onay zaman aşımı (devam ettirilebilir — harcamanız kaybolmaz) ve ileriye-sarma-olmayan (non-fast-forward) "uzak kök ilerledi" hatası. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Sorun giderme](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Okuma & doğrulama hataları {#read--verify-failures} +## Read & verify failures -Kanıt uyuşmazlığı, şifre çözme/tuz (salt) hataları ve bulunamadı / decoy yanıtları. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Okuma & doğrulama hataları](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Cüzdan & oturum sorunları {#wallet--session-issues} +## Wallet & session issues -Bağlanma, yeniden kimlik doğrulama, reddedilen bir istek ve imzalayamayan yalnızca-izleme oturumları. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [Cüzdan oturumu imzalayamıyor](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Ön uçuş & maliyet kontrolleri — bir capsule'ü boşa harcamayın {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (ortam + hazır olma), `--dry-run` (maliyeti ve olası capsule'ü önizler) ve `--if-changed` (bayt-özdeş bir build hiçbir işlem yapmaz). +The browser extension shows your node as offline even though it's running and healthy. -→ [GitHub Actions'tan dağıtım](../digstore/cli/deploy-from-github-actions.md) · [Zincir üzeri sabitleme → maliyet & güvenlik](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Hata kodları referansı {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI çıkış kodları · RPC `-32xxx` · DIGHUb · dig-loader · SDK — tek bir birleştirilmiş tablo. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Hata kodları](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## SSS {#faq} +## Error codes reference -Maliyet, ücretsiz deneme, fiyat neden tek tip, $DIG nereden alınır ve "bir testnet var mı?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. -→ [SSS](../support/faq.md) +→ [Error codes](../support/error-codes.md) -## Yardım alın {#get-help} +## FAQ -Discord + GitHub ve iyi bir rapor nasıl dosyalanır — **asla sır yapıştırmayın**. +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". -→ [Yardım alın](../support/get-help.md) +→ [FAQ](../support/faq.md) -## Durum & değişiklik günlüğü {#status--changelog} +## Get help -→ [Durum](../support/status.md) · [Değişiklik günlüğü](../support/changelog.md) +Discord + GitHub, and how to file a good report — **never paste secrets**. + +→ [Get help](../support/get-help.md) + +## Status & changelog + +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Daha derine inin: protokol {#go-deeper-the-protocol} +## Go deeper: the protocol -- **okuma & doğrulama hataları** → [Kanıtlar & güvenlik](../digstore/format/proofs-and-security.md) · [URN'ler & şifreleme](../digstore/format/urns-and-encryption.md) -- **RPC `-32xxx` kodları** → [dig RPC metotları](../rpc/methods.md) · [Uygunluk](../rpc/conformance.md) -- **Her şey** → [Protokol derinlemesine inceleme](../protocol-deep-dive.md) · [Kavramlar & sözlük](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/tr/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/tr/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/tr/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/tr/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/vi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 01360e8..4f3262a 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 -title: Xử lý sự cố — thoát khỏi bế tắc -description: "Mỗi lỗi đều cho bạn một mã ổn định và một request-id gắn thẳng vào log server, các giao dịch chi tiêu on-chain được bảo vệ khỏi tình trạng đua (race-guarded) nên bạn không bao giờ trả tiền hai lần, và các bảo vệ tiền kiểm rõ ràng ngăn lãng phí capsule trước khi bạn chi $DIG." +title: Troubleshooting — get unstuck +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# Xử lý sự cố {#troubleshooting} +# Troubleshooting -> Mỗi lỗi đều cho bạn một **mã ổn định** và một **request-id** gắn thẳng vào log server, các giao dịch chi tiêu on-chain được **bảo vệ khỏi tình trạng đua (race-guarded)** nên bạn không bao giờ trả tiền hai lần, và các **bảo vệ tiền kiểm** rõ ràng ngăn lãng phí capsule trước khi bạn chi $DIG. +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## Mô hình tư duy — tìm lỗi của bạn qua mã của nó {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -Mọi bề mặt — dig RPC, digstore CLI, DIGHUb, trình tải `chia://`, SDK — đều ánh xạ một lỗi thành một **mã ỔN ĐỊNH** duy nhất. **Rẽ nhánh dựa trên mã, không bao giờ dựa vào thông điệp.** Một danh mục hợp nhất bao quát tất cả và cũng được công bố dưới dạng máy đọc được. +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -Các bảo vệ tiền kiểm (`digstore doctor`, `--dry-run`, `--if-changed`) và các điểm neo có thể tiếp tục lại nghĩa là một lần xuất bản bị kẹt hoặc no-op **không bao giờ âm thầm tốn tiền**. +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## Các lỗi xuất bản thường gặp {#common-publishing-failures} +## Common publishing failures -Thiếu tiền, hết thời gian chờ xác nhận (có thể tiếp tục lại — giao dịch chi tiêu của bạn không bị mất), và lỗi "root từ xa đã tiến thêm" không-fast-forward. +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [Xử lý sự cố](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## Lỗi đọc & xác minh {#read--verify-failures} +## Read & verify failures -Bằng chứng không khớp, lỗi giải mã/salt, và các phản hồi không tìm thấy / decoy. +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [Lỗi đọc & xác minh](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## Sự cố ví & phiên làm việc {#wallet--session-issues} +## Wallet & session issues -Kết nối, xác thực lại, một yêu cầu bị từ chối, và các phiên chỉ-xem không thể ký. +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [Phiên ví không thể ký](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## Kiểm tra tiền kiểm & chi phí — đừng lãng phí một capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor` (môi trường + sự sẵn sàng), `--dry-run` (xem trước chi phí và capsule sẽ được tạo), và `--if-changed` (một bản build giống hệt byte-for-byte là no-op). +The browser extension shows your node as offline even though it's running and healthy. -→ [Triển khai từ GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [Neo on-chain → chi phí & an toàn](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## Tham khảo mã lỗi {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -Mã thoát CLI · RPC `-32xxx` · DIGHUb · dig-loader · SDK — một bảng hợp nhất duy nhất. +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [Mã lỗi](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## Câu hỏi thường gặp {#faq} +## Error codes reference -Chi phí, bản dùng thử miễn phí, tại sao mức giá lại đồng nhất, lấy $DIG ở đâu, và "có testnet không?". +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. -→ [Câu hỏi thường gặp](../support/faq.md) +→ [Error codes](../support/error-codes.md) -## Nhận trợ giúp {#get-help} +## FAQ -Discord + GitHub, và cách gửi một báo cáo tốt — **không bao giờ dán bí mật**. +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". -→ [Nhận trợ giúp](../support/get-help.md) +→ [FAQ](../support/faq.md) -## Trạng thái & nhật ký thay đổi {#status--changelog} +## Get help -→ [Trạng thái](../support/status.md) · [Nhật ký thay đổi](../support/changelog.md) +Discord + GitHub, and how to file a good report — **never paste secrets**. + +→ [Get help](../support/get-help.md) + +## Status & changelog + +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## Đi sâu hơn: giao thức {#go-deeper-the-protocol} +## Go deeper: the protocol -- **lỗi đọc & xác minh** → [Bằng chứng & bảo mật](../digstore/format/proofs-and-security.md) · [URN & mã hóa](../digstore/format/urns-and-encryption.md) -- **mã RPC `-32xxx`** → [các phương thức dig RPC](../rpc/methods.md) · [Tuân thủ](../rpc/conformance.md) -- **Tất cả** → [Đi sâu vào giao thức](../protocol-deep-dive.md) · [Khái niệm & thuật ngữ](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/vi/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index 3b24d67..4f3262a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 title: Troubleshooting — get unstuck -description: "每一次失败都会给你一个稳定的错误码和一个可以直接对应到服务器日志的 request-id,链上支出具备竞态防护因此你永远不会重复付款,清晰的预检防护会在花费 $DIG 之前拦截无谓的 capsule 浪费。" +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# 故障排查 {#troubleshooting} +# Troubleshooting -> 每一次失败都会给你一个**稳定的错误码**和一个可以直接对应到服务器日志的 **request-id**,链上支出具备**竞态防护**因此你永远不会重复付款,清晰的**预检防护**会在花费 $DIG 之前拦截无谓的 capsule 浪费。 +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## 心智模型 —— 通过错误码定位你的故障 {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -每一个接口 —— dig RPC、digstore CLI、DIGHUb、`chia://` 加载器、SDK —— 都会将一次失败映射到一个**稳定的错误码**。**始终基于错误码进行分支判断,绝不基于错误信息文字。** 一份统一的目录涵盖了所有这些错误码,并且同样以机器可读的形式发布。 +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -预检防护(`digstore doctor`、`--dry-run`、`--if-changed`)以及可续传的锚定操作,意味着一次卡住或无操作的发布**永远不会静默地产生花费**。 +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## 常见发布故障 {#common-publishing-failures} +## Common publishing failures -余额不足、确认超时(可续传 —— 你的支出不会丢失),以及非快进式的"remote root has advanced"(远程根已推进)错误。 +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [故障排查](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## 读取与验证故障 {#read--verify-failures} +## Read & verify failures -证明不匹配、解密/salt 错误,以及未找到 / 诱饵(decoy)响应。 +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [读取与验证故障](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## 钱包与会话问题 {#wallet--session-issues} +## Wallet & session issues -连接、重新认证、被拒绝的请求,以及无法签名的只读会话。 +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [钱包会话无法签名](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## 预检与费用检查 —— 不浪费一个 capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor`(环境与就绪状态检查)、`--dry-run`(预览费用和即将产生的 capsule),以及 `--if-changed`(字节完全相同的构建将不做任何操作)。 +The browser extension shows your node as offline even though it's running and healthy. -→ [从 GitHub Actions 部署](../digstore/cli/deploy-from-github-actions.md) · [链上锚定 → 费用与安全](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## 错误码参考 {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI 退出码 · RPC `-32xxx` · DIGHUb · dig-loader · SDK —— 一张统一的对照表。 +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [错误码](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## 常见问题 {#faq} +## Error codes reference -费用、免费试用、为什么价格是统一的、去哪里获取 $DIG,以及"有测试网吗?"。 +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. -→ [常见问题](../support/faq.md) +→ [Error codes](../support/error-codes.md) -## 获取帮助 {#get-help} +## FAQ -Discord + GitHub,以及如何提交一份高质量的问题报告 —— **切勿粘贴任何机密信息**。 +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". -→ [获取帮助](../support/get-help.md) +→ [FAQ](../support/faq.md) -## 状态与更新日志 {#status--changelog} +## Get help -→ [状态](../support/status.md) · [更新日志](../support/changelog.md) +Discord + GitHub, and how to file a good report — **never paste secrets**. + +→ [Get help](../support/get-help.md) + +## Status & changelog + +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## 深入了解:协议 {#go-deeper-the-protocol} +## Go deeper: the protocol -- **读取与验证故障** → [证明与安全](../digstore/format/proofs-and-security.md) · [URN 与加密](../digstore/format/urns-and-encryption.md) -- **RPC `-32xxx` 错误码** → [dig RPC 方法列表](../rpc/methods.md) · [一致性](../rpc/conformance.md) -- **完整内容** → [协议深度解析](../protocol-deep-dive.md) · [概念与术语表](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md index b636228..4f3262a 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/audiences/troubleshooting.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 -title: 疑難排解——解決卡關問題 -description: "每一次失敗都會提供一個穩定代碼與一個能直接對應到伺服器日誌的請求識別碼(request-id),鏈上花費具備競爭防護機制因此你絕不會重複付款,而明確的前置檢查機制則能在你花費 $DIG 之前,先攔下會被浪費的 capsule。" +title: Troubleshooting — get unstuck +description: "Every failure gives you a stable code and a request-id that ties straight to the server log, on-chain spends are race-guarded so you never double-pay, and clear pre-flight guards stop wasted capsules before you spend $DIG." keywords: - DIG troubleshooting - error codes @@ -16,66 +16,72 @@ tags: - capsule --- -# 疑難排解 {#troubleshooting} +# Troubleshooting -> 每一次失敗都會提供一個**穩定代碼**與一個能直接對應到伺服器日誌的**請求識別碼(request-id)**,鏈上花費具備**競爭防護機制**因此你絕不會重複付款,而明確的**前置檢查機制**則能在你花費 $DIG 之前,先攔下會被浪費的 capsule。 +> Every failure gives you a **stable code** and a **request-id** that ties straight to the server log, on-chain spends are **race-guarded** so you never double-pay, and clear **pre-flight guards** stop wasted capsules before you spend $DIG. -## 心智模型——依代碼找出你遇到的失敗原因 {#the-mental-model--find-your-failure-by-its-code} +## The mental model — find your failure by its code -每一個介面——dig RPC、digstore CLI、DIGHUb、`chia://` 載入器、SDK——都會將失敗對應到一個**穩定代碼**。**永遠依代碼分支處理,而非依錯誤訊息文字。** 有一份統一的分類表涵蓋所有介面,並以機器可讀格式發布。 +Every surface — the dig RPC, the digstore CLI, DIGHUb, the `chia://` loader, the SDK — maps a failure to one **STABLE code**. **Branch on the code, never the message.** One consolidated catalog covers all of them and is also published machine-readable. -前置檢查機制(`digstore doctor`、`--dry-run`、`--if-changed`)加上可續傳的錨定機制,代表卡住或無變化的發布**絕不會靜默地花費資金**。 +Pre-flight guards (`digstore doctor`, `--dry-run`, `--if-changed`) and resumable anchors mean a stuck or no-op publish **never silently spends**. -## 常見的發布失敗 {#common-publishing-failures} +## Common publishing failures -資金不足、確認逾時(可續傳——你的花費不會遺失),以及非快轉(non-fast-forward)的「遠端 root 已經推進」錯誤。 +Insufficient funds, a confirm timeout (resumable — your spend isn't lost), and the non-fast-forward "remote root has advanced". -→ [疑難排解](../support/troubleshooting.md) +→ [Troubleshooting](../support/troubleshooting.md) -## 讀取與驗證失敗 {#read--verify-failures} +## Read & verify failures -證明不符、解密/salt 錯誤,以及查無結果/誘餌(decoy)回應。 +Proof mismatch, decrypt/salt errors, and not-found / decoy responses. -→ [讀取與驗證失敗](../support/troubleshooting.md#verification-failed) +→ [Read & verify failures](../support/troubleshooting.md#verification-failed) -## 錢包與連線問題 {#wallet--session-issues} +## Wallet & session issues -連接、重新驗證、被拒絕的請求,以及無法簽署的唯讀(watch-only)連線。 +Connect, re-auth, a declined request, and watch-only sessions that can't sign. -→ [錢包連線無法簽署](../support/troubleshooting.md#wallet-session) +→ [Wallet session can't sign](../support/troubleshooting.md#wallet-session) -## 前置檢查與費用檢查——別浪費一個 capsule {#pre-flight--cost-checks--dont-waste-a-capsule} +## Node & extension issues -`digstore doctor`(環境與就緒狀態檢查)、`--dry-run`(預覽費用與將要產生的 capsule),以及 `--if-changed`(位元組完全相同的建置結果不會有任何動作)。 +The browser extension shows your node as offline even though it's running and healthy. -→ [從 GitHub Actions 部署](../digstore/cli/deploy-from-github-actions.md).[鏈上錨定 → 費用與安全性](../digstore/cli/onchain-anchoring.md#cost-and-safety) +→ [The extension shows my node as offline](../support/troubleshooting.md#extension-offline) -## 錯誤代碼參考 {#error-codes-reference} +## Pre-flight & cost checks — don't waste a capsule -CLI 結束代碼.RPC `-32xxx`.DIGHUb.dig-loader.SDK——統一收錄於一份表格中。 +`digstore doctor` (environment + readiness), `--dry-run` (preview the cost and the would-be capsule), and `--if-changed` (a byte-identical build is a no-op). -→ [錯誤代碼](../support/error-codes.md) +→ [Deploy from GitHub Actions](../digstore/cli/deploy-from-github-actions.md) · [On-chain anchoring → cost & safety](../digstore/cli/onchain-anchoring.md#cost-and-safety) -## 常見問答 {#faq} +## Error codes reference -費用、免費試用、為何價格是統一的、去哪裡取得 $DIG,以及「有測試網嗎?」。 +CLI exit codes · RPC `-32xxx` · DIGHUb · dig-loader · SDK — one consolidated table. -→ [常見問答](../support/faq.md) +→ [Error codes](../support/error-codes.md) -## 取得協助 {#get-help} +## FAQ -Discord 與 GitHub,以及如何提交一份完善的回報——**絕不貼上機密資訊**。 +Cost, the free trial, why the price is uniform, where to get $DIG, and "is there a testnet?". -→ [取得協助](../support/get-help.md) +→ [FAQ](../support/faq.md) -## 狀態與變更紀錄 {#status--changelog} +## Get help -→ [狀態](../support/status.md).[變更紀錄](../support/changelog.md) +Discord + GitHub, and how to file a good report — **never paste secrets**. + +→ [Get help](../support/get-help.md) + +## Status & changelog + +→ [Status](../support/status.md) · [Changelog](../support/changelog.md) --- -## 深入了解協定 {#go-deeper-the-protocol} +## Go deeper: the protocol -- **讀取與驗證失敗** → [證明與安全性](../digstore/format/proofs-and-security.md).[URN 與加密](../digstore/format/urns-and-encryption.md) -- **RPC `-32xxx` 代碼** → [dig RPC 方法列表](../rpc/methods.md).[一致性](../rpc/conformance.md) -- **完整內容** → [協定深入解析](../protocol-deep-dive.md).[概念與詞彙表](../concepts.md) +- **read & verify failures** → [Proofs & security](../digstore/format/proofs-and-security.md) · [URNs & encryption](../digstore/format/urns-and-encryption.md) +- **RPC `-32xxx` codes** → [the dig RPC methods](../rpc/methods.md) · [Conformance](../rpc/conformance.md) +- **Everything** → [Protocol deep-dive](../protocol-deep-dive.md) · [Concepts & glossary](../concepts.md) diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 578db8b..ef198ec 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -1,13 +1,16 @@ --- sidebar_position: 13 title: "L7 · DIG Node peer network" -description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." +description: "The normative node↔node protocol: mTLS peer identity (peer_id = SHA-256(TLS SPKI DER)), the two RPC tiers (mTLS-authenticated PEER/CONTROL vs anonymous PUBLIC-READ so browsers can retrieve content), the dual-mode public gateway (rpc.dig.net's mTLS front for node-class clients — the digstore CLI, the SDK, any DIG-identity-key holder — across the full dig.local/localhost/rpc.dig.net ladder, plus its plain-HTTPS+CORS front for browsers, with an ephemeral self-signed client certificate for channel-bound anonymous reads), the ordered NAT-traversal ladder (direct → UPnP → NAT-PMP → PCP → relay-coordinated hole-punch (signalling only) → relayed/TURN transport), the relay's four roles (STUN, introducer, hole-punch signalling, relayed transport), STUN reflexive-address discovery, introducer + gossip peer discovery, PEX peer-exchange (node↔node stream + the RLY-008 relay introducer binding), the Kademlia DHT with provider records that locate which peers hold content (find_node/find_providers/add_provider/ping over a framed dig-nat mTLS stream; content-key = SHA-256(domain-tag ‖ store_id[‖root[‖retrieval_key]])), the relay RelayMessage wire (RLY-001..RLY-008), the peer RPC methods (dig.getPeers/dig.announce/dig.getNetworkInfo/dig.getAvailability/dig.listInventory/dig.fetchRange), and the relay-last-fallback invariant (prefer hole-punch signalling over full relaying)." keywords: - peer network - peer_id - mTLS - dual transport - public read tier + - gateway dual-mode + - ephemeral client certificate + - node-class client - CORS - NAT traversal - STUN @@ -94,8 +97,8 @@ A `dig-node` runs **two listeners**: The **recommended endpoint split** (design-first call): the public read tier is the **same JSON-RPC endpoint shape** as the network profile — one `POST` endpoint speaking JSON-RPC 2.0 — but the anonymous serve layer answers **only the read subset**; the peer/write/control methods return `-32601` there. This reuses the existing [node-profile / `dig.methods` gating](./dig-rpc.md#node-profile) (an agent already gates on `dig.methods` rather than assuming one uniform surface) instead of inventing a parallel protocol, and it is exactly what a browser already speaks to `rpc.dig.net`. The peer/control tier is **not** a JSON-RPC-over-HTTPS surface at all — it is the dig-nat mTLS mux — so it cannot be reached by an anonymous HTTP client even by accident. -:::note `rpc.dig.net` IS the public read tier -Today `rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is exactly this anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier. This section names the tier the browser has always used and states the invariant that keeps the peer/write/control surface off it. +:::note `rpc.dig.net` is dual-mode: the public read tier plus an mTLS gateway +`rpc.dig.net` ([the dig RPC network profile](./dig-rpc.md)) is the anonymous, CORS-enabled, decoy-on-miss, client-verified public read tier — the tier a browser has always used, and this section states the invariant that keeps the peer/write/control surface off it. It is also the **public mTLS gateway**: node-class clients, and anonymous readers holding an ephemeral certificate, reach the very same hostname over the mTLS peer/control transport instead. [§0a](#gateway-dual-mode) is the two-front contract. ::: ### Browser specifics — fetch + verify without mTLS @@ -108,6 +111,35 @@ A browser (or an agent with no client certificate) reads content like this, need Because the read tier is CORS-`*` + anonymous, the exact same fetch works from a web page, a service worker, the extension, the SDK, or a headless agent — none of which can present a client certificate. +### 0a · `rpc.dig.net` is dual-mode — the public gateway serves both tiers {#gateway-dual-mode} + +`rpc.dig.net` is one public, network-wide hostname, but it is not one listener — it is the **public gateway**, answering on two independently-authenticated fronts so a node-class client and a browser both reach it correctly: + +| | **mTLS gateway front** | **Public-read front** | +|---|---|---| +| Who dials it | node-class clients — any DIG-identity-key holder: the `digstore` CLI, `dig-sdk`, a standalone `dig-node`, DIG Browser in standalone-node mode — plus anonymous readers using an [ephemeral certificate](#ephemeral-read-cert) | browsers, the extension's fetch path, headless agents with no client certificate | +| Auth | mTLS, `CERT_REQUIRED` — the same handshake as the [peer/control tier](#dual-transport) | none — plain HTTPS, CORS-`*` | +| Identity carried | the caller's `peer_id` derived from its presented cert ([§1](#peer-identity)) — persistent for a node-class client's own identity-derived cert, disposable for an ephemeral read cert | none | +| Methods reachable | the full [PEER/CONTROL surface](#tier-map) **and** the PUBLIC-READ methods, all over the mTLS channel | the [PUBLIC-READ surface](#tier-map) only | +| Write authorization | [§21.9 signed-request](./transport-and-push.md#per-request-auth), checked against the caller's identity | none — this front carries no write route | + +**A node-class client never uses the public-read front — not even for reads.** It resolves its endpoint through the fixed three-tier ladder — an explicit override wins outright, then `dig.local`, then `localhost`, then `rpc.dig.net` as the final fallback (see [Point a consumer at your node](../run-a-node/point-a-consumer.md) and [the digstore CLI's ladder](../digstore/cli/command-reference.md#which-node-digstore-talks-to)) — and at **every** tier of that ladder, including `rpc.dig.net`, it dials over mTLS with the client certificate derived from its DIG identity key ([§1](#peer-identity)), layering [§21.9](./transport-and-push.md#per-request-auth) over the channel for any guarded call. This is a hard rule, not an optimization: a node-class client downgraded to the anonymous front would lose its stable `peer_id` (never recognized as a returning peer for allowlisting, PEX, or reputation), lose access to the PEER/CONTROL methods a full read path may need (DHT lookups, availability-for-sync, multi-source [`dig.fetchRange`](#range)), and lose the channel-binding described next. + +#### Anonymous reads over the mTLS front — the ephemeral client certificate {#ephemeral-read-cert} + +An anonymous reader is not required to use the plain-HTTPS public-read front — it MAY instead dial the mTLS gateway front for **channel-bound** request integrity, at the cost of running a TLS client-cert handshake. The mTLS listener requires *a* certificate (`CERT_REQUIRED`), not a *known* one — peer identity is verified by the `peer_id` hash, not a CA ([§1](#peer-identity)) — so an anonymous caller satisfies the handshake with an **ephemeral, self-signed client certificate**: + +1. **Generate a throwaway keypair and a self-signed leaf**, scoped to the TLS session (or a short-lived batch of sessions) about to be opened. No registration and no persisted identity — the certificate exists only to complete the handshake. +2. **Complete the mTLS handshake** with it. The gateway derives a `peer_id` from it exactly as it would for any peer ([§1](#peer-identity)); this `peer_id` is disposable and carries **no reputation, no allowlisting, and no authorization** — it is a transport artifact, not a claimed identity. +3. **Issue the read** (`dig.getContent` or another [PUBLIC-READ](#tier-map) method) inside that authenticated channel, optionally carrying the same [§21.9-shaped](./transport-and-push.md#per-request-auth) signed-request headers a node-class client would send. +4. **The TLS session binds the request.** A signed request that travels inside a channel authenticated by that specific ephemeral certificate cannot be replayed over a *different* TLS session while still inside its [300-second freshness window](./transport-and-push.md#per-request-auth) — the channel itself becomes part of what a verifier can require to match. This is strictly additive integrity over the plain-HTTPS front, which binds a request to nothing. + +The read itself is governed by the same rules regardless of which front carried it: read-only, no mutation, [client-side self-verification](#dual-transport) against the chain-anchored root, decoy-on-miss ([§7a](#tier-map)). **Reaching the mTLS front never grants an anonymous caller a PEER/CONTROL method** — the [boundary invariant](#the-boundary-invariant) is enforced by what the request names, not by which front carried it; an ephemeral-cert caller naming a peer/write/config method gets the same [`-32601`](./dig-rpc.md#error-model) a plain-HTTPS caller would. + +:::caution Design status — gate on the gateway mTLS endpoint +The `rpc.dig.net` mTLS front described in this section is a **normative design contract**, not yet a live endpoint — today `rpc.dig.net` serves only the plain-HTTPS public-read front, and existing node-class clients still reach it that way for reads. This is a rollout transition, not a standing exception to the rule above: an implementation MUST NOT hard-break (crash, refuse to run, or treat the gateway as unreachable) merely because the mTLS front does not exist yet. It gates on the front's presence — a capability probe or a handshake attempt — and, only while that probe fails, continues reaching `rpc.dig.net` over the plain-HTTPS front for reads, never for peer/write/config methods (which simply are not reachable there, [§7a](#tier-map)). Once the mTLS front is deployed, every node-class client switches to it at the `rpc.dig.net` tier, closing this transition. +::: + ## 1 · Peer identity + mTLS {#peer-identity} A peer is identified by the SHA-256 of the DER-encoded `SubjectPublicKeyInfo` of the certificate it presents in the TLS handshake: @@ -128,6 +160,7 @@ peer_id = SHA-256( SubjectPublicKeyInfo DER ) // 32 bytes - **The listener requires a client certificate** (`CERT_REQUIRED`). A peer that presents no certificate, or whose TLS handshake fails, is dropped — there is no fallback to a weaker transport. - **After the TLS handshake, peers exchange a `Handshake`** carrying the `network_id` (the network genesis challenge as lower-case hex), the protocol version, the node's declared listen port, and its node type + capabilities. A `network_id` mismatch, or a protocol version below the minimum-compatible floor, ends the connection. The `Handshake` is the Chia-streamable message (big-endian) — this layer speaks the Chia peer protocol, not a bespoke framing. - **Unauthenticated peer traffic is rejected.** A message received before a completed mTLS handshake + `Handshake` exchange is not processed. +- **The mainnet genesis challenge is not yet public**, so a stock `dig-node` uses an all-zero placeholder for `network_id` and skips peer bring-up entirely (the read path — serving/fetching capsules — is unaffected). A developer or private deployment that wants the peer network up today can set the `DIG_NETWORK_GENESIS` environment variable to a 64-character hex value (32 bytes); any valid non-zero value brings the gossip peer pool up under that id. See [Configure dig-node](../run-a-node/configure.md). :::note The relay link is authenticated differently A node's link *to the relay* is a standard server-authenticated `wss://` connection (the relay presents a TLS certificate; the node does not present one to the relay). Peer↔peer identity is never delegated to the relay — end-to-end payloads carried over the relay remain authenticated by the peer protocol itself, so a relay cannot forge a peer. @@ -374,16 +407,19 @@ The implementers' contract for the [dual-transport tiers](#dual-transport). The | `dig.getPeers` / `dig.announce` / `dig.getNetworkInfo` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.getAvailability` / `dig.listInventory` | **PEER / CONTROL** | mTLS | dig-nat mTLS | | `dig.fetchRange` (peer sync / multi-source) | **PEER / CONTROL** | mTLS | dig-nat mTLS | +| `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` (read) | **PEER / CONTROL** | mTLS | dig-nat mTLS | | DHT `find_node` / `find_providers` / `add_provider` / `ping` ([§4c](#dht)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | PEX `pex_handshake` / `pex_snapshot` / `pex_delta` / `pex_error` ([§4d](#pex)) | **PEER / CONTROL** | mTLS (node↔node) or registered relay identity (RLY-008) | dig-nat mTLS stream / relay WebSocket | +| onion circuit cells (`dig.onion` stream: `CREATE`/`EXTEND`/`RELAY`/`DESTROY`) ([onion routing](./onion-routing.md)) | **PEER / CONTROL** | mTLS | dig-nat mTLS stream | | §21 PUSH / WRITE: `module/upload` · `module` PUT · `module/complete` · `tombstone` | **PEER / CONTROL** | mTLS + per-request BLS ([§21.9](./transport-and-push.md#per-request-auth)) | authenticated HTTPS | -| node config / control (`cache.*`, `control.*`, `dig.stage`, `dig.getAnchoredRoot`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | +| node config / control (`cache.*`, `control.*`, `dig.stage`) | **CONTROL (loopback)** | local authorization (loopback-only) | local FFI / loopback HTTP | Notes: - **`dig.getAvailability` / `dig.fetchRange` are PEER/CONTROL**, not public read: they are the node↔node **sync/multi-source** surface, ridden over the mTLS mux. The browser/agent public read path is the [dig RPC](./dig-rpc.md) (`dig.getContent` et al.) — a browser does not fan byte-ranges across peers; that is a node-side operation ([multi-source download](#multi-source)). -- **`dig.getAnchoredRoot` and `cache.*` are local control** (loopback / in-process FFI, [node profile](./dig-rpc.md#node-profile)), not exposed on the public read listener. A browser resolves the anchored root from its own chain source, not from the serving node. +- **The peer JSON-RPC surface is an allowlist.** Because the mTLS client-cert verifier accepts any well-formed self-signed leaf, "authenticated" means only "some `peer_id`", not "authorized". The peer surface therefore answers ONLY the read / discovery / announce methods above (`dig.getContent`, `dig.getAvailability`, `dig.listInventory`, `dig.fetchRange`, `dig.getNetworkInfo`, `dig.getPeers`, `dig.announce`, `dig.getAnchoredRoot`, `dig.getCollection`, `dig.listCollectionItems`) and returns [`-32601`](./dig-rpc.md#error-model) for every `cache.*` / `control.*` / `dig.stage` method — those are loopback / in-process only. `dig.getAnchoredRoot` / `dig.getCollection` / `dig.listCollectionItems` are read-only, owner-independent chain reads and are peer-reachable; `cache.*` / `control.*` / `dig.stage` mutate or read local state and are not. - **The read subset is identical in shape to the [network profile](./dig-rpc.md)** — this is why one JSON-RPC endpoint serves both a browser and the local consumer; only the *set of methods the anonymous listener answers* differs. +- **`rpc.dig.net` answers on two fronts, not two tiers.** The dual-mode gateway ([§0a](#gateway-dual-mode)) exposes the PEER/CONTROL column over its mTLS front (to node-class clients and ephemeral-cert anonymous readers) alongside the PUBLIC-READ column over its plain-HTTPS front — a method's tier assignment in this table never changes; only which transport a given caller uses to reach it differs. ## 7 · Peer RPC methods (node profile) {#peer-rpc} @@ -478,7 +514,7 @@ This mirrors the [dig RPC streaming contract](./dig-rpc.md#streaming) (window/of ## 9 · Byte-range content fetch + multi-source download {#range} -A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the same multisource + range + integrity + resume model implemented by the `dig-download-utility` reference. +A node can request a specific **byte range** `[offset, offset+length)` of a content resource or an entire `.dig` capsule, and receive **only those bytes**, streamed. This is the primitive behind **multi-source download**: a client splits a resource into ranges and fetches **different ranges from different peers simultaneously**, verifies each independently, and reassembles — the multisource + range + integrity + resume model the node-side download engine implements. ### Availability first — ask before you fetch {#availability} @@ -684,6 +720,7 @@ The peer network is implemented by several crates that must interoperate byte-fo | **`peer_id`** | `SHA-256(SubjectPublicKeyInfo DER)` → `Bytes32`, 64-hex on text surfaces | the identity every peer derives for every other peer; a mismatch means no interop | | **mTLS handshake** | `wss://` + client cert required + Chia `Handshake` (hex `network_id`, protocol version, node type) | that a peer link is authenticated and network-scoped before any message is processed | | **Two RPC tiers** | PEER/CONTROL = mTLS-authenticated (peer/DHT/PEX/availability-for-sync/write/config); PUBLIC-READ = anonymous, CORS-`*`, read-only, client-verified, decoy-on-miss ([§0](#dual-transport), [tier map §7a](#tier-map)). No peer/write/config method reachable without mTLS; content read requires no mTLS | that a browser can retrieve+verify content with no client cert while every mutation/identity/peer surface stays mTLS-gated — the boundary invariant is uniform across every serve layer + client | +| **Gateway dual-mode** | `rpc.dig.net` serves a plain-HTTPS anonymous public-read front (CORS-`*`, no client cert) and an mTLS front (`CERT_REQUIRED`) for node-class-client identity certs and ephemeral anonymous read certs ([§0a](#gateway-dual-mode)) | that a node-class client is never silently downgraded to the anonymous path even at the public gateway, and an anonymous mTLS reader gets channel-bound request integrity while carrying no identity or reputation | | **RelayMessage wire** | the RLY-001..RLY-008 JSON shapes in [§6](#relayed), `type`-tagged, `payload` as a byte array, `from` re-stamped, `network_id`-scoped; RLY-008 = the additive [PEX](#pex) binding | that any relay + any node speak the same rendezvous/hole-punch/relayed/PEX wire | | **PEX** | the four `pex_*` messages ([§4d](#pex)) with the `dig-pex/SPEC.md` shapes; two bindings — dig-nat mux stream (u32-BE+JSON, `PEX_MAX_FRAME` 262144) and the relay [RLY-008](#relayed) (additive WS frames, introducer-only, registration-backed `via:"introducer"`); entries are hints (first-hand rule, `via` provenance, strike-mute); `addresses[]` byte-compatible with `dig.getPeers`/DHT `Contact` | that peer gossip is anti-flood + first-hand across both transports, entries are verified-before-trusted, and PEX-learned contacts drop straight into a dial target | | **Relay error codes** | `1..4` (`NOT_REGISTERED`/`BAD_MESSAGE`/`PEER_NOT_FOUND`/`CAPACITY`) | deterministic relay-side failure signalling | @@ -702,6 +739,8 @@ A reimplementation of any peer crate conforms iff it reproduces these — the sa ## Related +- [Point a consumer at your node](../run-a-node/point-a-consumer.md) — the three-tier client→node resolution ladder (`dig.local` → `localhost` → `rpc.dig.net`) and how a node-class client dials mTLS across all of it, including the `rpc.dig.net` gateway's [mTLS front](#gateway-dual-mode) +- [Private retrieval (onion routing)](./onion-routing.md) — the PRIVACY retrieval mode: telescoping onion circuits over these mTLS peer links, the `dig.onion` stream, and the onion-relay directory - [The dig RPC](./dig-rpc.md) — the PUBLIC READ tier: what a browser/agent reads over anonymous JSON-RPC; the node profile the peer RPC extends - [§21 transport & push](./transport-and-push.md) — the §21 GET (public read) vs PUSH/WRITE (mTLS peer/control) split - [BLS signatures & DSTs](./bls-signatures.md) — the node/attestation signatures carried over peer links; the per-request write auth on the control tier diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/support/troubleshooting.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/support/troubleshooting.md index 13982a2..af8ddd6 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/support/troubleshooting.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/support/troubleshooting.md @@ -107,6 +107,18 @@ Confirm the store has at least one confirmed capsule; `"latest"` on a brand-new Not an error — you cancelled the signature in your wallet. Nothing was signed or broadcast. Re-try and approve if you meant to publish. +## Node & browser extension + +### "The extension shows my node as offline" {#extension-offline} + +Your `dig-node` is running and `/health` answers fine, but the DIG browser extension still reports it offline. + +Modern Chrome enforces **Private Network Access**: it blocks a page/extension request to a private address (127.0.0.1 included) unless the node's CORS preflight response allows it. Older `dig-node` builds didn't send that allowance. + +- Update to the latest `dig-node` release (v0.13.0 or later) and restart the service. +- Reload the extension after the node restarts. +- Still offline? Confirm you're hitting the node directly at its configured port, not a stale cached connection — reload the extension's own background/service-worker context too. + ## CLI setup ### "no seed found" {#no-seed} diff --git a/package.json b/package.json index d147eaf..ac883ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docs-dig-net", - "version": "0.3.18", + "version": "0.3.19", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/static/openrpc-node.json b/static/openrpc-node.json index 801f778..69d2623 100644 --- a/static/openrpc-node.json +++ b/static/openrpc-node.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "dig RPC — node profile (local dig-node / in-process DIG Browser)", - "version": "0.3.18", + "version": "0.3.19", "description": "The NODE PROFILE: a distinct, smaller surface than the network profile. Of the byte methods it implements ONLY dig.getContent (local-first, else proxy); everything else proxies upstream or returns -32601. It ADDS node-only methods the security model depends on — chiefly dig.getAnchoredRoot (the CHIP-0035 on-chain head, the trusted root for mandatory root-pinning), dig.stage, and cache.*. Gate on dig.methods rather than assuming one uniform surface. See https://docs.dig.net/docs/protocol/dig-rpc#node-profile.", "license": { "name": "GPL-2.0", diff --git a/static/openrpc.json b/static/openrpc.json index 50a96ae..bdca999 100644 --- a/static/openrpc.json +++ b/static/openrpc.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "dig RPC — DIG Network Content Interface (network profile)", - "version": "0.3.18", + "version": "0.3.19", "description": "The network-wide read interface for DIG content over JSON-RPC 2.0 — the NETWORK PROFILE served by the canonical node at rpc.dig.net. Blind by construction (the node holds no URN and no key), verifiable without trust (merkle inclusion proofs against the chain-anchored root), and streamable at any size. There is no `decoy` field on the wire and no CDN. See https://docs.dig.net/docs/protocol/dig-rpc.", "license": { "name": "GPL-2.0",