Milestone 4: LAN discovery, trust gate, auto-sync, rate limits, events
mDNS-style LAN discovery (iroh MdnsDiscovery, discovery flag, default on) feeds a presence tracker; trusted peers that appear trigger fetches of every incomplete pin, and Pin itself now fetches from present trusted peers. Serving is our own ProtocolHandler: trusted NodeIds get the full store, everyone else a filtered view limited to open_lan pins and ticket-exported hashes (plus hashseq children) that answers "not found" for the rest. Ticket export records standing serve-consent for that hash; trust changes take effect on new connections. ShapedStore implements the full iroh-blobs Store trait to charge provider reads to an upload token bucket and downloader writes to a download bucket; upload cap 0 closes incoming connections at accept. Subscribe now streams transfer_progress both ways, peer_joined, and pin_complete. Tests: forged-ticket trust gating (denied untrusted, served after trust), 256 KiB/s upload cap enforced by wall clock, event stream during a transfer, and real-mdns auto-sync between two daemons (skips where multicast is unavailable). Dependencies: n0-future, async-channel, futures-lite, bytes — all already in the tree via iroh; needed directly to name types in iroh-blobs trait signatures and channels. iroh feature discovery-local-network for MdnsDiscovery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -313,6 +313,25 @@ impl BlobStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// The child hashes of a complete HashSeq root (empty for absent or
|
||||
/// partial roots).
|
||||
pub async fn hashseq_children(&self, root: Hash) -> Result<Vec<Hash>, OpError> {
|
||||
self.on_pool(move |this| async move {
|
||||
let Some(entry) = this.store.get(&root).await? else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
if !entry.is_complete() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let mut reader = entry.data_reader();
|
||||
let bytes = reader.read_to_end().await?;
|
||||
let seq = HashSeq::try_from(bytes)
|
||||
.map_err(|e| OpError::Internal(anyhow::anyhow!("invalid hashseq: {e}")))?;
|
||||
Ok(seq.iter().collect())
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Drop every blob not reachable from `roots` (mark and sweep).
|
||||
/// In-flight imports are protected by their temp tags; tags stored in
|
||||
/// the blob database are honored too.
|
||||
|
||||
Reference in New Issue
Block a user