Migrate to iroh 1.0 and iroh-blobs 0.103

The 0.35 pin's rationale ("the post-0.35 rewrite is not yet production
quality") expired when iroh hit 1.0 in June 2026: the rewrite line
(0.103) is now the production line and the only one receiving fixes.

The rewrite replaced wrappable store traits with an irpc-based API, so
the seams moved:

- shaped.rs: the 440-line ShapedStore trait wrapper becomes a provider
  event handler. Trust gating (untrusted peers see only openly-served
  hashes) now intercepts requests before any bytes move; upload rate
  limiting rides the provider's Throttle hook; upload progress events
  come from per-request update streams. The TokenBucket is unchanged.
- store.rs: FsStore's API handle replaces the store traits, and the
  LocalPool machinery for non-Send futures is gone. GC is now the
  store's built-in periodic mark-and-sweep, fed by a pin-roots snapshot
  via the protect callback (new config knob gc_interval_secs, default
  300); the on-demand Gc request answers Unimplemented, and the gc
  conformance test polls the sweep instead.
- transfer.rs: BlobsProtocol + Router replace handle_connection, the
  new multi-provider Downloader replaces the old queue, and mdns
  discovery moved to the iroh-mdns-address-lookup crate (it left iroh
  core in 1.0). Ticket-embedded provider addresses feed a MemoryLookup
  address book. Endpoint presets: Minimal (LAN-only default) or N0
  (wan_upload), preserving the old relay posture.
- Node* became Endpoint* throughout; announcement signatures use iroh's
  own Signature type (ed25519-dalek dep dropped); iroh-io dropped.

Known regression: max_download_bytes_per_sec is currently not enforced
— download shaping rode the old store's batch writer and 0.103's
downloader has no equivalent seam yet.

Announcement wire format note: EndpointAddr serializes differently than
NodeAddr, so pre- and post-migration daemons won't parse each other's
LAN announcements. Announcements are live-only, nothing stored breaks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Lynghaug
2026-08-16 14:03:15 +02:00
co-authored by Claude Fable 5
parent a2d150225a
commit ad69f7d884
14 changed files with 1807 additions and 2248 deletions
+9 -9
View File
@@ -18,7 +18,7 @@ use std::pin::Pin;
use std::sync::Arc;
use anyhow::Result;
use iroh::{NodeAddr, NodeId, PublicKey, SecretKey};
use iroh::{EndpointAddr, EndpointId, PublicKey, SecretKey};
use iroh_blobs::Hash;
use n0_future::Stream;
use serde::{Deserialize, Serialize};
@@ -47,7 +47,7 @@ pub struct Announcement {
/// Free-form metadata (name hints, sizes, provenance...).
pub meta: BTreeMap<String, String>,
/// Peers believed to hold the content.
pub providers: Vec<NodeAddr>,
pub providers: Vec<EndpointAddr>,
}
/// An [`Announcement`] plus the author's signature over it and its topic.
@@ -83,7 +83,7 @@ impl SignedAnnouncement {
.as_slice()
.try_into()
.map_err(|_| anyhow::anyhow!("signature must be 64 bytes"))?;
let signature = ed25519_dalek::Signature::from_bytes(bytes);
let signature = iroh::Signature::from_bytes(bytes);
self.announcement
.author
.verify(&payload, &signature)
@@ -96,7 +96,7 @@ impl SignedAnnouncement {
/// are excluded — they are hints that relays may legitimately refresh —
/// but the provider identities are covered.
fn signing_payload(topic: TopicKey, announcement: &Announcement) -> Result<Vec<u8>> {
let provider_ids: Vec<NodeId> = announcement.providers.iter().map(|p| p.node_id).collect();
let provider_ids: Vec<EndpointId> = announcement.providers.iter().map(|p| p.id).collect();
let payload = (
topic,
announcement.root,
@@ -127,7 +127,7 @@ pub trait DiscoveryProvider: Send + Sync {
/// broadcasts its content list.
pub struct LanDiscovery {
secret: SecretKey,
sightings: std::sync::Mutex<Option<mpsc::Receiver<NodeId>>>,
sightings: std::sync::Mutex<Option<mpsc::Receiver<EndpointId>>>,
/// Snapshot of locally pinned roots, queried per sighting.
pins: Arc<dyn Fn() -> Vec<Hash> + Send + Sync>,
}
@@ -135,7 +135,7 @@ pub struct LanDiscovery {
impl LanDiscovery {
pub fn new(
secret: SecretKey,
sightings: mpsc::Receiver<NodeId>,
sightings: mpsc::Receiver<EndpointId>,
pins: Arc<dyn Fn() -> Vec<Hash> + Send + Sync>,
) -> LanDiscovery {
LanDiscovery {
@@ -165,7 +165,7 @@ impl DiscoveryProvider for LanDiscovery {
root,
author: secret.public(),
meta: BTreeMap::from([("source".to_string(), "mdns".to_string())]),
providers: vec![NodeAddr::new(node_id)],
providers: vec![EndpointAddr::new(node_id)],
};
match SignedAnnouncement::sign(&secret, LAN_TOPIC, announcement) {
Ok(signed) => {
@@ -197,7 +197,7 @@ mod tests {
use super::*;
fn keypair() -> SecretKey {
SecretKey::generate(rand::rngs::OsRng)
SecretKey::generate()
}
fn sample(author: PublicKey) -> Announcement {
@@ -205,7 +205,7 @@ mod tests {
root: Hash::new(b"content"),
author,
meta: BTreeMap::from([("name".to_string(), "demo".to_string())]),
providers: vec![NodeAddr::new(keypair().public())],
providers: vec![EndpointAddr::new(keypair().public())],
}
}