51 lines
2.8 KiB
Markdown
51 lines
2.8 KiB
Markdown
|
|
# Milestone 3 — Transfer
|
||
|
|
|
||
|
|
The daemon now has an iroh endpoint: it serves its store over
|
||
|
|
`iroh_blobs::ALPN` via the standard `Blobs`/`Router` stack, and fetches
|
||
|
|
pinned content with the iroh-blobs `Downloader`. `TicketExport` /
|
||
|
|
`TicketImport` complete the v1 out-of-band sharing loop; the pin created
|
||
|
|
by an import triggers the fetch from the ticket-embedded provider.
|
||
|
|
|
||
|
|
## Decisions
|
||
|
|
|
||
|
|
- **Endpoint identity** is an ed25519 key at `<store_dir>/secret.key`
|
||
|
|
(hex, mode `0600`, created on first start). Node ids surface in the
|
||
|
|
API as opaque strings in iroh's canonical encoding.
|
||
|
|
- **Relay disabled unless `wan_upload = true`.** The default posture is
|
||
|
|
LAN-only with zero WAN upload; with the relay off the endpoint is only
|
||
|
|
reachable over direct paths and never moves bytes through third-party
|
||
|
|
infrastructure. Tickets between machines that can't reach each other
|
||
|
|
directly need `wan_upload` on both ends — documented behavior, not a
|
||
|
|
bug.
|
||
|
|
- **Downloader, not the rpc client.** The `Blobs` rpc client
|
||
|
|
(`add_from_path`/`download`) would pull in the whole quic-rpc feature
|
||
|
|
surface; the underlying `Downloader` gives queueing, retries and
|
||
|
|
resume with no extra dependencies. One found-the-hard-way detail: the
|
||
|
|
downloader dials by NodeId only, so the ticket's `NodeAddr` must be
|
||
|
|
registered with the endpoint (`add_node_addr`) before queueing, or
|
||
|
|
every dial fails with "no addressing information".
|
||
|
|
- **Pin-before-fetch.** `TicketImport` records the pin (and the format
|
||
|
|
from the ticket) before the fetch starts: the pin is the GC root that
|
||
|
|
protects in-flight data, and the standing intent survives an
|
||
|
|
unreachable provider or a crash. Re-issuing the import after a crash
|
||
|
|
resumes from iroh-blobs' on-disk partial state.
|
||
|
|
- **Fetches are background tasks.** `TicketImport` replies immediately
|
||
|
|
with the pinned hash; completion is observable via `Status {hash}`
|
||
|
|
polling or the `pin_complete` event on a subscribed connection.
|
||
|
|
- **A bare `Pin` still fetches nothing** — there are no known providers
|
||
|
|
until LAN discovery lands in milestone 4. The pin is recorded and the
|
||
|
|
spec's "fetch if absent" activates when provider sources exist.
|
||
|
|
- **No serving gate yet**: this milestone serves any peer that presents
|
||
|
|
the hash (tickets are unguessable capability tokens; BLAKE3 hashes of
|
||
|
|
private content should be treated as secrets). The trust allowlist
|
||
|
|
gate is milestone 4's first change.
|
||
|
|
|
||
|
|
## Tests
|
||
|
|
|
||
|
|
Two-daemon localhost integration: single blob and directory collection
|
||
|
|
transfer, byte-identical after materialize on the fetcher. Crash test:
|
||
|
|
SIGKILL the fetcher ~150 ms into a 64 MB transfer, restart on the same
|
||
|
|
store, re-import the ticket, content completes and matches (proves
|
||
|
|
clean restart with partial on-disk state; on a fast machine the kill
|
||
|
|
may land after completion, which still exercises restart-with-state).
|