From ad69f7d884b9bf1f4a85e9f5ff08036391847630 Mon Sep 17 00:00:00 2001 From: Bendik Lynghaug Date: Sun, 16 Aug 2026 14:03:15 +0200 Subject: [PATCH] Migrate to iroh 1.0 and iroh-blobs 0.103 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- Cargo.lock | 2683 ++++++++++++++----------------- Cargo.toml | 9 +- README.md | 2 +- SPECS.md | 4 +- varde-ctl/tests/roundtrip.rs | 1 + varde-daemon/Cargo.toml | 18 +- varde-daemon/src/config.rs | 8 + varde-daemon/src/daemon.rs | 66 +- varde-daemon/src/discovery.rs | 18 +- varde-daemon/src/shaped.rs | 504 ++---- varde-daemon/src/store.rs | 360 ++--- varde-daemon/src/transfer.rs | 313 ++-- varde-daemon/tests/lan_trust.rs | 9 +- varde-daemon/tests/store_ops.rs | 60 +- 14 files changed, 1807 insertions(+), 2248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0ae10a..911ef59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,14 +4,15 @@ version = 4 [[package]] name = "acto" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a026259da4f1a13b4af60cda453c392de64c58c12d239c560923e0382f42f2b9" +checksum = "598381761ee991bf2f1455f700380e2191fb370dc9df1ee764f348b7f089d8b6" dependencies = [ "parking_lot", "pin-project-lite", "rustc_version", "smol_str", + "sync_wrapper", "tokio", "tracing", ] @@ -22,21 +23,33 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "bytes", - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] [[package]] -name = "ahash" -version = "0.8.12" +name = "aes" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "once_cell", - "version_check", - "zerocopy", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", ] [[package]] @@ -119,6 +132,15 @@ version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -133,9 +155,9 @@ checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "asn1-rs" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -143,15 +165,15 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.18", "time", ] [[package]] name = "asn1-rs-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", @@ -182,31 +204,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-compat" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ba85bc55464dcbf728b56d97e119d673f4cf9062be330a9a26f3acf504a590" -dependencies = [ - "futures-core", - "futures-io", - "once_cell", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-recursion" version = "1.1.1" @@ -286,9 +283,9 @@ dependencies = [ [[package]] name = "bao-tree" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff16d65e48353db458be63ee395c03028f24564fd48668389bd65fd945f5ac36" +checksum = "06384416b1825e6e04fde63262fda2dc408f5b64c02d04e0d8b70ae72c17a52b" dependencies = [ "blake3", "bytes", @@ -298,20 +295,16 @@ dependencies = [ "positioned-io", "range-collections", "self_cell", + "serde", "smallvec", + "tokio", ] [[package]] name = "base16ct" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64" @@ -337,7 +330,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", ] [[package]] @@ -347,10 +340,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] -name = "bitflags" -version = "1.3.2" +name = "bit-vec" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] [[package]] name = "bitflags" @@ -374,18 +370,21 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] -name = "bounded-integer" -version = "0.5.8" +name = "block2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102dbef1187b1893e6dfe05a774e79fd52265f49f214f6879c8ff49f52c8188b" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] [[package]] name = "bumpalo" @@ -418,6 +417,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" @@ -430,17 +435,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - [[package]] name = "chacha20" version = "0.10.1" @@ -463,7 +457,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -472,9 +466,8 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", - "zeroize", ] [[package]] @@ -517,6 +510,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "cobs" version = "0.3.0" @@ -532,6 +531,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -543,9 +552,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.6" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "constant_time_eq" @@ -553,6 +562,15 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cordyceps" version = "0.3.4" @@ -573,6 +591,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -597,21 +625,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - [[package]] name = "critical-section" version = "1.2.0" @@ -642,18 +655,6 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.7" @@ -661,54 +662,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] [[package]] -name = "crypto_box" -version = "0.9.1" +name = "crypto-common" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "aead", - "chacha20 0.9.1", - "crypto_secretbox", - "curve25519-dalek", - "salsa20", - "serdect", - "subtle", - "zeroize", + "hybrid-array", + "rand_core 0.10.1", ] [[package]] -name = "crypto_secretbox" -version = "0.1.1" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "aead", - "chacha20 0.9.1", "cipher", - "generic-array", - "poly1305", - "salsa20", - "subtle", - "zeroize", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] name = "curve25519-dalek" -version = "4.1.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", "curve25519-dalek-derive", "digest", "fiat-crypto", - "rand_core 0.6.4", + "rand_core 0.10.1", "rustc_version", "serde", "subtle", @@ -726,6 +722,41 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.118", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.118", +] + [[package]] name = "data-encoding" version = "2.11.0" @@ -733,22 +764,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] -name = "der" -version = "0.7.10" +name = "data-encoding-macro" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" +dependencies = [ + "data-encoding", + "syn 2.0.118", +] + +[[package]] +name = "der" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" dependencies = [ "const-oid", - "der_derive", "pem-rfc7468", "zeroize", ] [[package]] name = "der-parser" -version = "9.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ "asn1-rs", "displaydoc", @@ -759,21 +809,41 @@ dependencies = [ ] [[package]] -name = "der_derive" -version = "0.7.3" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", "proc-macro2", "quote", "syn 2.0.118", ] [[package]] -name = "deranged" -version = "0.5.8" +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.118", +] [[package]] name = "derive_more" @@ -781,7 +851,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl 2.1.1", ] [[package]] @@ -796,6 +875,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.118", + "unicode-xid", +] + [[package]] name = "diatomic-waker" version = "0.2.3" @@ -804,14 +897,24 @@ checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" [[package]] name = "digest" -version = "0.10.7" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer", - "const-oid", - "crypto-common", - "subtle", + "crypto-common 0.2.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", ] [[package]] @@ -827,88 +930,47 @@ dependencies = [ [[package]] name = "dlopen2" -version = "0.5.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ "libc", "once_cell", "winapi", ] -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - [[package]] name = "ed25519" -version = "2.2.3" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" dependencies = [ "pkcs8", - "serde", + "serdect", "signature", ] [[package]] name = "ed25519-dalek" -version = "2.2.0" +version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core 0.6.4", + "rand_core 0.10.1", "serde", "sha2", + "signature", "subtle", "zeroize", ] [[package]] -name = "elliptic-curve" -version = "0.13.8" +name = "either" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "embedded-io" @@ -929,15 +991,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "enum-assoc" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "872ece5a3d5aa63541e400219676c38e8f5474cf3366834c3f2d1fe23d29bc55" dependencies = [ - "heck", "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.3", ] [[package]] @@ -999,10 +1060,16 @@ dependencies = [ ] [[package]] -name = "fallible-iterator" -version = "0.3.0" +name = "fastbloom" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8" +dependencies = [ + "foldhash", + "libm", + "portable-atomic", + "siphasher", +] [[package]] name = "fastrand" @@ -1010,21 +1077,11 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "fiat-crypto" -version = "0.2.9" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" [[package]] name = "find-msvc-tools" @@ -1032,18 +1089,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin 0.9.9", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1052,9 +1097,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" @@ -1221,8 +1266,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link", + "windows-result", ] [[package]] @@ -1233,7 +1278,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -1256,11 +1300,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -1278,10 +1320,14 @@ dependencies = [ ] [[package]] -name = "glob" -version = "0.3.3" +name = "ghash" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] [[package]] name = "gloo-timers" @@ -1295,17 +1341,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "h2" version = "0.4.15" @@ -1336,39 +1371,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "hashlink" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" -dependencies = [ - "hashbrown 0.14.5", -] - [[package]] name = "heapless" version = "0.7.17" @@ -1389,12 +1400,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" @@ -1402,82 +1407,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hickory-proto" -version = "0.25.2" +name = "hickory-net" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" dependencies = [ "async-trait", + "bytes", "cfg-if", "data-encoding", - "enum-as-inner", "futures-channel", "futures-io", "futures-util", + "h2", + "hickory-proto", + "http", "idna", "ipnet", - "once_cell", - "rand 0.9.5", - "ring", + "jni 0.22.4", + "rand 0.10.2", + "rustls", "thiserror 2.0.18", "tinyvec", "tokio", + "tokio-rustls", + "tracing", + "url", +] + +[[package]] +name = "hickory-proto" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni 0.22.4", + "once_cell", + "prefix-trie", + "rand 0.10.2", + "ring", + "thiserror 2.0.18", + "tinyvec", "tracing", "url", ] [[package]] name = "hickory-resolver" -version = "0.25.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" dependencies = [ "cfg-if", "futures-util", + "hickory-net", "hickory-proto", "ipconfig", + "ipnet", + "jni 0.22.4", "moka", + "ndk-context", "once_cell", "parking_lot", - "rand 0.9.5", + "rand 0.10.2", "resolv-conf", + "rustls", "smallvec", + "system-configuration", "thiserror 2.0.18", "tokio", + "tokio-rustls", "tracing", ] -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "hmac-sha1" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b05da5b9e5d4720bfb691eebb2b9d42da3570745da71eac8a1f5bb7e59aab88" -dependencies = [ - "hmac", - "sha1", -] - -[[package]] -name = "hmac-sha256" -version = "1.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9d92d097f4749b64e8cc33d924d9f40a2d4eb91402b458014b781f5733d60f" - -[[package]] -name = "hostname-validator" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" - [[package]] name = "http" version = "1.4.2" @@ -1523,6 +1528,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.10.1" @@ -1558,7 +1572,6 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.8", ] [[package]] @@ -1578,7 +1591,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.5", + "socket2", "tokio", "tower-service", "tracing", @@ -1596,7 +1609,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -1690,6 +1703,18 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "identity-hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdd7caa900436d8f13b2346fe10257e0c05c1f1f9e351f4f5d57c03bd5f45da" + [[package]] name = "idna" version = "1.1.0" @@ -1713,11 +1738,10 @@ dependencies = [ [[package]] name = "igd-next" -version = "0.16.2" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +checksum = "de7238d487a9aff61f81b5ab41c0a841532a115a398b5fa92a2fadd0885e2581" dependencies = [ - "async-trait", "attohttpc", "bytes", "futures", @@ -1726,7 +1750,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.9.5", + "rand 0.10.2", "tokio", "url", "xmltree", @@ -1739,7 +1763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown", ] [[package]] @@ -1760,28 +1784,16 @@ dependencies = [ "smallvec", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "ipconfig" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.6.5", + "socket2", "widestring", "windows-registry", - "windows-result 0.4.1", + "windows-result", "windows-sys 0.61.2", ] @@ -1790,58 +1802,52 @@ name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "iroh" -version = "0.35.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca758f4ce39ae3f07de922be6c73de6a48a07f39554e78b5745585652ce38f5" +checksum = "5fca9b4b462c343ff88fc0af4096c186f939b602a0bc08723536ef2c31c93971" dependencies = [ - "aead", - "anyhow", - "atomic-waker", "backon", + "blake3", "bytes", "cfg_aliases", - "concurrent-queue", - "crypto_box", + "ctutils", "data-encoding", - "der", - "derive_more", + "derive_more 2.1.1", "ed25519-dalek", - "futures-buffered", "futures-util", - "getrandom 0.3.4", + "getrandom 0.4.3", "hickory-resolver", "http", - "igd-next", - "instant", + "ipnet", "iroh-base", + "iroh-dns", "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "iroh-quinn-udp", "iroh-relay", - "n0-future", - "netdev", + "n0-error", + "n0-future 0.3.2", + "n0-watcher", "netwatch", + "noq", + "noq-proto", + "noq-udp", + "papaya", "pin-project", - "pkarr", + "portable-atomic", "portmapper", - "rand 0.8.7", - "rcgen", + "rand 0.10.2", "reqwest", - "ring", + "rustc-hash", "rustls", - "rustls-webpki 0.102.8", + "rustls-pki-types", "serde", "smallvec", - "spki", "strum", - "stun-rs", - "surge-ping", - "swarm-discovery", - "thiserror 2.0.18", "time", "tokio", "tokio-stream", @@ -1849,78 +1855,90 @@ dependencies = [ "tracing", "url", "wasm-bindgen-futures", - "webpki-roots 0.26.11", - "x509-parser", - "z32", ] [[package]] name = "iroh-base" -version = "0.35.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91ac4aaab68153d726c4e6b39c30f9f9253743f0e25664e52f4caeb46f48d11" +checksum = "6be73e16ee21c923aca9b3121aaa0db936f7c7ecc156ff47b8dac944c68d59a8" dependencies = [ "curve25519-dalek", "data-encoding", - "derive_more", + "data-encoding-macro", + "derive_more 2.1.1", "ed25519-dalek", - "postcard", - "rand_core 0.6.4", + "getrandom 0.4.3", + "n0-error", + "rand 0.10.2", "serde", - "thiserror 2.0.18", "url", + "zeroize", ] [[package]] name = "iroh-blobs" -version = "0.35.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "817b785193b73c34ef1f2dcb5ddf8729ecef9b72a8fc0e706ee6d7a9bf8766a6" +checksum = "5be50b0e2d0a9ba65cee4e0dfb708b3704e02ad12bd4c14c6307e94245943126" dependencies = [ - "anyhow", - "async-channel", + "arrayvec", "bao-tree", - "blake3", "bytes", + "cfg_aliases", "chrono", + "constant_time_eq", "data-encoding", - "derive_more", - "futures-buffered", - "futures-lite", - "futures-util", + "derive_more 2.1.1", "genawaiter", - "hashlink", + "getrandom 0.4.3", "hex", "iroh", "iroh-base", "iroh-io", "iroh-metrics", - "nested_enum_utils 0.1.0", - "num_cpus", - "oneshot", - "parking_lot", - "portable-atomic", + "iroh-tickets", + "iroh-util", + "irpc", + "n0-error", + "n0-future 0.3.2", + "nested_enum_utils", + "noq", "postcard", - "quic-rpc", - "quic-rpc-derive", - "rand 0.8.7", + "rand 0.10.2", "range-collections", "redb", + "ref-cast", "reflink-copy", "self_cell", "serde", - "serde-error", "smallvec", - "ssh-key", - "strum", - "tempfile", - "thiserror 2.0.18", "tokio", - "tokio-util", "tracing", - "tracing-futures", - "tracing-test", - "walkdir", +] + +[[package]] +name = "iroh-dns" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516e4eedc38e33ab69a6bd325520332dc3d67b25454e2d590ebb84a25240dd9a" +dependencies = [ + "arc-swap", + "cfg_aliases", + "derive_more 2.1.1", + "hickory-resolver", + "iroh-base", + "n0-error", + "n0-future 0.3.2", + "ndk-context", + "portable-atomic", + "rand 0.10.2", + "rustls", + "simple-dns", + "strum", + "tokio", + "tracing", + "url", ] [[package]] @@ -1937,23 +1955,45 @@ dependencies = [ ] [[package]] -name = "iroh-metrics" -version = "0.34.0" +name = "iroh-mdns-address-lookup" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70466f14caff7420a14373676947e25e2917af6a5b1bec45825beb2bf1eb6a7" +checksum = "7c1f941695731bc3999d8c13d7e94d50e229427da81ac957eec3818264f17559" +dependencies = [ + "data-encoding", + "derive_more 2.1.1", + "futures-util", + "iroh", + "iroh-base", + "n0-error", + "n0-future 0.3.2", + "n0-watcher", + "swarm-discovery", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "iroh-metrics" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291065721ad7c477b972e581bbc528df031dc8eb5e39fe1ff3300ae5dfb157ef" dependencies = [ "iroh-metrics-derive", "itoa", + "n0-error", + "portable-atomic", + "ryu", "serde", - "snafu", "tracing", ] [[package]] name = "iroh-metrics-derive" -version = "0.2.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d12f5c45c4ed2436302a4e03cad9a0ad34b2962ad0c5791e1019c0ee30eeb09" +checksum = "1ae5f0c4405d1fbc9fb16ff422ca40620e93dc36c30ecaba0c2aee3992b7bd48" dependencies = [ "heck", "proc-macro2", @@ -1961,105 +2001,111 @@ dependencies = [ "syn 2.0.118", ] -[[package]] -name = "iroh-quinn" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c6245c9ed906506ab9185e8d7f64857129aee4f935e899f398a3bd3b70338d" -dependencies = [ - "bytes", - "cfg_aliases", - "iroh-quinn-proto", - "iroh-quinn-udp", - "pin-project-lite", - "rustc-hash", - "rustls", - "socket2 0.5.10", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-proto" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929d5d8fa77d5c304d3ee7cae9aede31f13908bd049f9de8c7c0094ad6f7c535" -dependencies = [ - "bytes", - "getrandom 0.2.17", - "rand 0.8.7", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-udp" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53afaa1049f7c83ea1331f5ebb9e6ebc5fdd69c468b7a22dd598b02c9bcc973" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.10", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "iroh-relay" -version = "0.35.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c63f122cdfaa4b4e0e7d6d3921d2b878f42a0c6d3ee5a29456dc3f5ab5ec931f" +checksum = "8149bb6a57126225a07d6928846d82dcedfd24ea0f863ef7b2eb475e1d726354" dependencies = [ - "anyhow", + "blake3", "bytes", "cfg_aliases", "data-encoding", - "derive_more", - "getrandom 0.3.4", + "derive_more 2.1.1", + "getrandom 0.4.3", "hickory-resolver", "http", "http-body-util", "hyper", "hyper-util", "iroh-base", + "iroh-dns", "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "lru 0.12.5", - "n0-future", + "lru", + "n0-error", + "n0-future 0.3.2", + "noq", + "noq-proto", "num_enum", "pin-project", - "pkarr", "postcard", - "rand 0.8.7", + "rand 0.10.2", "reqwest", "rustls", - "rustls-webpki 0.102.8", + "rustls-pki-types", "serde", - "sha1", + "serde_bytes", "strum", - "stun-rs", - "thiserror 2.0.18", "tokio", "tokio-rustls", "tokio-util", "tokio-websockets", "tracing", "url", - "webpki-roots 0.26.11", + "vergen-gitcl", + "webpki-roots", "ws_stream_wasm", - "z32", +] + +[[package]] +name = "iroh-tickets" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da53233419ca36bf521ed45683b7748366f9b233032891eefc2d70567a84ac54" +dependencies = [ + "data-encoding", + "derive_more 2.1.1", + "iroh-base", + "n0-error", + "postcard", + "serde", +] + +[[package]] +name = "iroh-util" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e41eb982f15230c55f0a70a74a514360e1f565b07861924fd0e8db172b3d00" +dependencies = [ + "derive_more 2.1.1", + "iroh", + "n0-error", + "n0-future 0.3.2", + "tokio", + "tracing", +] + +[[package]] +name = "irpc" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3623d6ff582b415904b29bbe6ebcb4a4f9a262ccdee05a45fdd003ef0950c386" +dependencies = [ + "futures-buffered", + "futures-util", + "irpc-derive", + "n0-error", + "n0-future 0.3.2", + "noq", + "postcard", + "rcgen", + "rustls", + "serde", + "smallvec", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "irpc-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c254013736de16472140d26904e6ac98e8f3887284dcf4af40f88c77411b56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", ] [[package]] @@ -2074,6 +2120,80 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.118", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.118", +] + [[package]] name = "js-sys" version = "0.3.103" @@ -2090,9 +2210,6 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin 0.9.9", -] [[package]] name = "libc" @@ -2118,12 +2235,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - [[package]] name = "lock_api" version = "0.4.14" @@ -2154,25 +2265,25 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.5" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +checksum = "5d2f2f9b4ba7e6b24d95e7e899329d35be83bcded72c8540cdd5368932d1d90a" dependencies = [ - "hashbrown 0.15.5", + "hashbrown", ] -[[package]] -name = "lru" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" - [[package]] name = "lru-slab" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac-addr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d25b0e0b648a86960ac23b7ad4abb9717601dec6f66c165f5b037f3f03065f" + [[package]] name = "matchers" version = "0.2.0" @@ -2182,12 +2293,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - [[package]] name = "memchr" version = "2.8.3" @@ -2237,6 +2342,27 @@ dependencies = [ "uuid", ] +[[package]] +name = "n0-error" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" +dependencies = [ + "n0-error-macros", + "spez", +] + +[[package]] +name = "n0-error-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2acd8b070213b0299282f884b4beba4e7b52d624fdcd504a3ad3665390c11e1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "n0-future" version = "0.1.3" @@ -2244,7 +2370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794" dependencies = [ "cfg_aliases", - "derive_more", + "derive_more 1.0.0", "futures-buffered", "futures-lite", "futures-util", @@ -2259,26 +2385,43 @@ dependencies = [ ] [[package]] -name = "nanorand" -version = "0.7.0" +name = "n0-future" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +checksum = "e2ab99dfb861450e68853d34ae665243a88b8c493d01ba957321a1e9b2312bbe" dependencies = [ - "getrandom 0.2.17", + "cfg_aliases", + "derive_more 2.1.1", + "futures-buffered", + "futures-lite", + "futures-util", + "js-sys", + "pin-project", + "send_wrapper", + "tokio", + "tokio-util", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-time", ] [[package]] -name = "nested_enum_utils" -version = "0.1.0" +name = "n0-watcher" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f256ef99e7ac37428ef98c89bef9d84b590172de4bbfbe81b68a4cd3abadb32" +checksum = "bbc618745ad0b7414b149d0517ad8b5573b2fb4d4e2717add3d2446ce1fdd826" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", + "derive_more 2.1.1", + "n0-error", + "n0-future 0.3.2", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "nested_enum_utils" version = "0.2.3" @@ -2293,81 +2436,61 @@ dependencies = [ [[package]] name = "netdev" -version = "0.31.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f901362e84cd407be6f8cd9d3a46bccf09136b095792785401ea7d283c79b91d" +checksum = "569dfbdd2efd771b24ec9bb57f956e04d4fbfc72f62b2f11961723f9b3f4b020" dependencies = [ + "block2", + "dispatch2", "dlopen2", "ipnet", + "jni 0.21.1", "libc", + "mac-addr", + "ndk-context", "netlink-packet-core", - "netlink-packet-route 0.17.1", + "netlink-packet-route", "netlink-sys", + "objc2", + "objc2-core-foundation", + "objc2-core-wlan", + "objc2-foundation", + "objc2-system-configuration", "once_cell", - "system-configuration", - "windows-sys 0.52.0", + "plist", + "windows-sys 0.61.2", ] [[package]] name = "netlink-packet-core" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +checksum = "b897d7bd4f0af82e68d40d0344cf37e97f9c97ddf74a098de3e4da05e96ca395" dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", + "paste", ] [[package]] name = "netlink-packet-route" -version = "0.17.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", - "libc", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-route" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0800eae8638a299eaa67476e1c6b6692922273e0f7939fd188fc861c837b9cd2" -dependencies = [ - "anyhow", - "bitflags 2.13.0", - "byteorder", + "bitflags", "libc", "log", "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-utils" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", ] [[package]] name = "netlink-proto" -version = "0.11.5" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" +checksum = "93af8261786086024cd5e96e0a991dd65ced07bbf7c233a487bbc96b971d5539" dependencies = [ "bytes", - "futures", + "futures-channel", + "futures-util", "log", "netlink-packet-core", "netlink-sys", @@ -2389,43 +2512,41 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.5.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eeaa5f7505c93c5a9b35ba84fd21fb8aa3f24678c76acfe8716af7862fb07a" +checksum = "4d9cbe01741347ef750d743d6690603f5eed8341e679fb51c8e629337aa11976" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", - "derive_more", - "iroh-quinn-udp", + "derive_more 2.1.1", + "ipnet", "js-sys", "libc", - "n0-future", - "nested_enum_utils 0.2.3", + "n0-error", + "n0-future 0.3.2", + "n0-watcher", "netdev", "netlink-packet-core", - "netlink-packet-route 0.23.0", + "netlink-packet-route", "netlink-proto", "netlink-sys", + "noq-udp", + "objc2-core-foundation", + "objc2-system-configuration", + "pin-project-lite", "serde", - "snafu", - "socket2 0.5.10", + "socket2", "time", "tokio", "tokio-util", "tracing", "web-sys", - "windows 0.59.0", - "windows-result 0.3.4", + "windows", + "windows-result", "wmi", ] -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - [[package]] name = "nom" version = "7.1.3" @@ -2437,18 +2558,67 @@ dependencies = [ ] [[package]] -name = "ntimestamp" -version = "1.0.0" +name = "noq" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50f94c405726d3e0095e89e72f75ce7f6587b94a8bd8dc8054b73f65c0fd68c" +checksum = "4bf95190af1bd4a00a10e8255ca0c8ddd9e9a9f5e79151d7a7eb6d56aff5dc89" dependencies = [ - "base32", - "document-features", - "getrandom 0.2.17", - "httpdate", - "js-sys", - "once_cell", - "serde", + "bytes", + "cfg_aliases", + "derive_more 2.1.1", + "noq-proto", + "noq-udp", + "pin-project-lite", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "web-time", +] + +[[package]] +name = "noq-proto" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa7b5ccd819a9c68a0d955e67a881032d09b1a17219b1f90b0997a0888e1a15" +dependencies = [ + "aes-gcm", + "bytes", + "derive_more 2.1.1", + "enum-assoc", + "fastbloom", + "getrandom 0.4.3", + "identity-hash", + "lru-slab", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "sorted-index-buffer", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "noq-udp" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3137a52df66c20090a889828d1c655f21f52294cba64e5c4fbb04fc83eee7c8e" +dependencies = [ + "cfg_aliases", + "libc", + "socket2", + "tracing", + "windows-sys 0.61.2", ] [[package]] @@ -2470,22 +2640,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.7", - "smallvec", - "zeroize", -] - [[package]] name = "num-conv" version = "0.2.2" @@ -2501,16 +2655,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2518,17 +2662,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", ] [[package]] @@ -2554,10 +2687,109 @@ dependencies = [ ] [[package]] -name = "oid-registry" -version = "0.7.1" +name = "num_threads" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", + "block2", + "dispatch2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-core-wlan" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e34919aba0d701380d911702455038a8a3587467fe0141d6a71501e7ffe48" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-security", + "objc2-security-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-security-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef76382e9cedd18123099f17638715cc3d81dba3637d4c0d39ab69df2ef345a5" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "bitflags", + "dispatch2", + "libc", + "objc2", + "objc2-core-foundation", + "objc2-security", +] + +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ "asn1-rs", ] @@ -2578,18 +2810,18 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "oneshot" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269bca4c2591a28585d6bf10d9ed0332b7d76900a1b02bec41bdc3a2cdcda107" - [[package]] name = "opaque-debug" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "ordered-stream" version = "0.2.0" @@ -2601,41 +2833,13 @@ dependencies = [ ] [[package]] -name = "p256" -version = "0.13.2" +name = "papaya" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p384" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p521" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" -dependencies = [ - "base16ct", - "ecdsa", - "elliptic-curve", - "primeorder", - "rand_core 0.6.4", - "sha2", + "equivalent", + "seize", ] [[package]] @@ -2664,7 +2868,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -2685,9 +2889,9 @@ dependencies = [ [[package]] name = "pem-rfc7468" -version = "0.7.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" dependencies = [ "base64ct", ] @@ -2698,48 +2902,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "pest" -version = "2.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.118", -] - -[[package]] -name = "pest_meta" -version = "2.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" -dependencies = [ - "pest", -] - [[package]] name = "pharos" version = "0.5.3" @@ -2776,106 +2938,36 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkarr" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb1f2f4311bae1da11f930c804c724c9914cf55ae51a9ee0440fc98826984f7" -dependencies = [ - "async-compat", - "base32", - "bytes", - "cfg_aliases", - "document-features", - "dyn-clone", - "ed25519-dalek", - "futures-buffered", - "futures-lite", - "getrandom 0.2.17", - "log", - "lru 0.13.0", - "ntimestamp", - "reqwest", - "self_cell", - "serde", - "sha1_smol", - "simple-dns", - "thiserror 2.0.18", - "tokio", - "tracing", - "url", - "wasm-bindgen-futures", -] - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - [[package]] name = "pkcs8" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" dependencies = [ "der", "spki", ] [[package]] -name = "pnet_base" -version = "0.34.0" +name = "plist" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ - "no-std-net", + "base64", + "indexmap", + "quick-xml", + "serde", + "time", ] [[package]] -name = "pnet_macros" -version = "0.34.0" +name = "polyval" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "syn 2.0.118", -] - -[[package]] -name = "pnet_macros_support" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" -dependencies = [ - "pnet_base", -] - -[[package]] -name = "pnet_packet" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" -dependencies = [ - "glob", - "pnet_base", - "pnet_macros", - "pnet_macros_support", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ + "cfg-if", "cpufeatures 0.2.17", "opaque-debug", "universal-hash", @@ -2886,30 +2978,31 @@ name = "portable-atomic" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +dependencies = [ + "serde", +] [[package]] name = "portmapper" -version = "0.5.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6db66007eac4a0ec8331d0d20c734bd64f6445d64bbaf0d0a27fea7a054e36" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64", "bytes", - "derive_more", - "futures-lite", - "futures-util", + "derive_more 2.1.1", "hyper-util", "igd-next", "iroh-metrics", "libc", - "nested_enum_utils 0.2.3", + "n0-error", + "n0-future 0.3.2", "netwatch", "num_enum", - "rand 0.8.7", + "rand 0.10.2", "serde", "smallvec", - "snafu", - "socket2 0.5.10", + "socket2", "time", "tokio", "tokio-util", @@ -2978,46 +3071,14 @@ dependencies = [ ] [[package]] -name = "precis-core" -version = "0.1.11" +name = "prefix-trie" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2e7b31f132e0c6f8682cfb7bf4a5340dbe925b7986618d0826a56dfe0c8e56" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" dependencies = [ - "precis-tools", - "ucd-parse", - "unicode-normalization", -] - -[[package]] -name = "precis-profiles" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e2768890a47af73a032af9f0cedbddce3c9d06cf8de201d5b8f2436ded7674" -dependencies = [ - "lazy_static", - "precis-core", - "precis-tools", - "unicode-normalization", -] - -[[package]] -name = "precis-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cc1eb2d5887ac7bfd2c0b745764db89edb84b856e4214e204ef48ef96d10c4a" -dependencies = [ - "lazy_static", - "regex", - "ucd-parse", -] - -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", + "either", + "ipnet", + "num-traits", ] [[package]] @@ -3077,11 +3138,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set", - "bit-vec", - "bitflags 2.13.0", + "bit-vec 0.8.0", + "bitflags", "num-traits", "rand 0.9.5", - "rand_chacha 0.9.0", + "rand_chacha", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -3089,40 +3150,6 @@ dependencies = [ "unarray", ] -[[package]] -name = "quic-rpc" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18bad98bd048264ceb1361ff9d77a031535d8c1e3fe8f12c6966ec825bf68eb7" -dependencies = [ - "anyhow", - "document-features", - "flume", - "futures-lite", - "futures-sink", - "futures-util", - "pin-project", - "serde", - "slab", - "smallvec", - "time", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "quic-rpc-derive" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf13f1bced5f2f2642d9d89a29d75f2d81ab34c4acfcb434c209d6094b9b2b7" -dependencies = [ - "proc-macro2", - "quic-rpc", - "quote", - "syn 1.0.109", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -3130,59 +3157,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] -name = "quinn" -version = "0.11.11" +name = "quick-xml" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2 0.6.5", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" -dependencies = [ - "bytes", - "getrandom 0.4.3", - "lru-slab", - "rand 0.10.2", - "rand_pcg", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.6.5", - "tracing", - "windows-sys 0.61.2", + "memchr", ] [[package]] @@ -3194,16 +3174,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "quoted-string-parser" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc75379cdb451d001f1cb667a9f74e8b355e9df84cc5193513cbe62b96fc5e9" -dependencies = [ - "pest", - "pest_derive", -] - [[package]] name = "r-efi" version = "5.3.0" @@ -3216,24 +3186,13 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "rand_chacha 0.9.0", + "rand_chacha", "rand_core 0.9.5", ] @@ -3243,21 +3202,11 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "chacha20 0.10.1", + "chacha20", "getrandom 0.4.3", "rand_core 0.10.1", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_chacha" version = "0.9.0" @@ -3268,15 +3217,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - [[package]] name = "rand_core" version = "0.9.5" @@ -3319,27 +3259,29 @@ dependencies = [ "binary-merge", "inplace-vec-builder", "ref-cast", + "serde", "smallvec", ] [[package]] name = "rcgen" -version = "0.13.2" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +checksum = "091e7a8e7d86e6feb87a27ce8e2cba29d49eff9507afeebefab7eeb2ca667fb4" dependencies = [ "pem", "ring", "rustls-pki-types", "time", + "x509-parser", "yasna", ] [[package]] name = "redb" -version = "2.4.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0a72cd7140de9fc3e318823b883abf819c20d478ec89ce880466dc2ef263c6" +checksum = "8e925444704b5f17d32bf42f5b6e2df050bceebc3dcd6e71cc73dafe8092e839" dependencies = [ "libc", ] @@ -3350,7 +3292,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.0", + "bitflags", ] [[package]] @@ -3382,19 +3324,7 @@ dependencies = [ "cfg-if", "libc", "rustix", - "windows 0.62.2", -] - -[[package]] -name = "regex" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "windows", ] [[package]] @@ -3408,12 +3338,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-lite" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" - [[package]] name = "regex-syntax" version = "0.8.11" @@ -3422,9 +3346,9 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", @@ -3440,12 +3364,9 @@ dependencies = [ "log", "percent-encoding", "pin-project-lite", - "quinn", "rustls", "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", + "rustls-platform-verifier", "sync_wrapper", "tokio", "tokio-rustls", @@ -3458,7 +3379,6 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.8", ] [[package]] @@ -3467,16 +3387,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - [[package]] name = "ring" version = "0.17.14" @@ -3491,27 +3401,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "sha2", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.3" @@ -3542,7 +3431,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -3559,11 +3448,23 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.13", + "rustls-webpki", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pki-types" version = "1.15.0" @@ -3575,16 +3476,32 @@ dependencies = [ ] [[package]] -name = "rustls-webpki" -version = "0.102.8" +name = "rustls-platform-verifier" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", + "core-foundation 0.10.1", + "core-foundation-sys", + "jni 0.22.4", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", ] +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.13" @@ -3620,15 +3537,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -3638,6 +3546,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -3651,17 +3568,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sec1" -version = "0.7.3" +name = "security-framework" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "bitflags", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "seize" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", ] [[package]] @@ -3693,12 +3629,13 @@ dependencies = [ ] [[package]] -name = "serde-error" -version = "0.1.3" +name = "serde_bytes" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342110fb7a5d801060c885da03bf91bfa7c7ca936deafcc64bb6706375605d47" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -3754,39 +3691,16 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serdect" -version = "0.2.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" dependencies = [ "base16ct", "serde", ] -[[package]] -name = "sha1" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest", -] - [[package]] name = "sha1_smol" version = "1.0.1" @@ -3795,12 +3709,12 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.9" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", "digest", ] @@ -3831,12 +3745,18 @@ dependencies = [ [[package]] name = "signature" -version = "2.2.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" dependencies = [ - "digest", - "rand_core 0.6.4", + "rustc_version", + "simdutf8", ] [[package]] @@ -3847,13 +3767,19 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "simple-dns" -version = "0.9.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" +checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags 2.13.0", + "bitflags", ] +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + [[package]] name = "slab" version = "0.4.12" @@ -3875,37 +3801,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" -[[package]] -name = "snafu" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" -dependencies = [ - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.118", -] - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "socket2" version = "0.6.5" @@ -3916,6 +3811,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "sorted-index-buffer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea06cc588e43c632923a55450401b8f25e628131571d4e1baea1bdfdb2b5ed06" + +[[package]] +name = "spez" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "spin" version = "0.9.9" @@ -3933,56 +3845,14 @@ checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" [[package]] name = "spki" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" dependencies = [ "base64ct", "der", ] -[[package]] -name = "ssh-cipher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" -dependencies = [ - "cipher", - "ssh-encoding", -] - -[[package]] -name = "ssh-encoding" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" -dependencies = [ - "base64ct", - "pem-rfc7468", - "sha2", -] - -[[package]] -name = "ssh-key" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" -dependencies = [ - "ed25519-dalek", - "p256", - "p384", - "p521", - "rand_core 0.6.4", - "rsa", - "sec1", - "sha2", - "signature", - "ssh-cipher", - "ssh-encoding", - "subtle", - "zeroize", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3997,83 +3867,42 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck", "proc-macro2", "quote", - "rustversion", "syn 2.0.118", ] -[[package]] -name = "stun-rs" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb921f10397d5669e1af6455e9e2d367bf1f9cebcd6b1dd1dc50e19f6a9ac2ac" -dependencies = [ - "base64", - "bounded-integer", - "byteorder", - "crc", - "enumflags2", - "fallible-iterator", - "hmac-sha1", - "hmac-sha256", - "hostname-validator", - "lazy_static", - "md5", - "paste", - "precis-core", - "precis-profiles", - "quoted-string-parser", - "rand 0.9.5", -] - [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "surge-ping" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30498e9c9feba213c3df6ed675bdf75519ccbee493517e7225305898c86cac05" -dependencies = [ - "hex", - "parking_lot", - "pnet_packet", - "rand 0.9.5", - "socket2 0.6.5", - "thiserror 1.0.69", - "tokio", - "tracing", -] - [[package]] name = "swarm-discovery" -version = "0.3.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a95032b94c1dc318f55e0b130e3d2176cda022310a65c3df0092764ea69562" +checksum = "1b4877f20f064de34b77d79237c9caa37c393590af8ef5a2f3253d59be5a338b" dependencies = [ "acto", - "anyhow", "hickory-proto", - "rand 0.8.7", - "socket2 0.5.10", + "rand 0.10.2", + "socket2", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -4100,6 +3929,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn-mid" version = "0.5.4" @@ -4133,12 +3973,12 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.13.0", - "core-foundation", + "bitflags", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4228,7 +4068,9 @@ checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "js-sys", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -4287,7 +4129,7 @@ dependencies = [ "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.5", + "socket2", "tokio-macros", "tracing", "windows-sys 0.61.2", @@ -4337,26 +4179,26 @@ dependencies = [ "futures-sink", "futures-util", "pin-project-lite", - "slab", "tokio", ] [[package]] name = "tokio-websockets" -version = "0.11.4" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fcaf159b4e7a376b05b5bfd77bfd38f3324f5fce751b4213bfc7eaa47affb4e" +checksum = "d52efb639344a7c6adb8e62c6f3d2c19c001ff1b79a5041ba1c6ed42e19c6aa5" dependencies = [ "base64", "bytes", "futures-core", "futures-sink", - "getrandom 0.3.4", + "getrandom 0.4.3", "http", "httparse", - "rand 0.9.5", + "rand 0.10.2", "ring", "rustls-pki-types", + "sha1_smol", "simdutf8", "tokio", "tokio-rustls", @@ -4455,7 +4297,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.13.0", + "bitflags", "bytes", "futures-util", "http", @@ -4512,16 +4354,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -4551,27 +4383,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "tracing-test" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a4c448db514d4f24c5ddb9f73f2ee71bfb24c526cf0c570ba142d1119e0051" -dependencies = [ - "tracing-core", - "tracing-subscriber", - "tracing-test-macro", -] - -[[package]] -name = "tracing-test-macro" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad06847b7afb65c7866a36664b75c40b895e318cea4f71299f013fb22965329d" -dependencies = [ - "quote", - "syn 2.0.118", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -4584,21 +4395,6 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" -[[package]] -name = "ucd-parse" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" -dependencies = [ - "regex-lite", -] - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - [[package]] name = "uds_windows" version = "1.2.1" @@ -4623,13 +4419,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] -name = "unicode-normalization" -version = "0.1.25" +name = "unicode-segmentation" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-xid" @@ -4643,7 +4436,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] @@ -4714,17 +4507,14 @@ name = "varde-daemon" version = "0.1.0" dependencies = [ "anyhow", - "async-channel", "bytes", - "ed25519-dalek", - "futures-lite", "iroh", "iroh-blobs", - "iroh-io", - "n0-future", + "iroh-mdns-address-lookup", + "irpc", + "n0-future 0.1.3", "postcard", "proptest", - "rand 0.8.7", "reflink-copy", "serde", "serde_json", @@ -4746,6 +4536,43 @@ dependencies = [ "serde_json", ] +[[package]] +name = "vergen" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ff3b5300a085d6bcd8fc96a507f706a28ae3814693236c9b409db71a1d15b9" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.5" @@ -4852,9 +4679,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -4884,12 +4711,12 @@ dependencies = [ ] [[package]] -name = "webpki-roots" -version = "0.26.11" +name = "webpki-root-certs" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" dependencies = [ - "webpki-roots 1.0.8", + "rustls-pki-types", ] [[package]] @@ -4938,16 +4765,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" -dependencies = [ - "windows-core 0.59.0", - "windows-targets 0.53.5", -] - [[package]] name = "windows" version = "0.62.2" @@ -4955,7 +4772,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ "windows-collections", - "windows-core 0.62.2", + "windows-core", "windows-future", "windows-numerics", ] @@ -4966,20 +4783,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" -dependencies = [ - "windows-implement 0.59.0", - "windows-interface", - "windows-result 0.3.4", - "windows-strings 0.3.1", - "windows-targets 0.53.5", + "windows-core", ] [[package]] @@ -4988,11 +4792,11 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement 0.60.2", + "windows-implement", "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -5001,22 +4805,11 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", "windows-threading", ] -[[package]] -name = "windows-implement" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.118", -] - [[package]] name = "windows-implement" version = "0.60.2" @@ -5039,12 +4832,6 @@ dependencies = [ "syn 2.0.118", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -5057,8 +4844,8 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", ] [[package]] @@ -5067,18 +4854,9 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -5087,16 +4865,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -5105,7 +4874,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -5117,22 +4895,28 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -5144,39 +4928,28 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link 0.2.1", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5184,10 +4957,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" +name = "windows_aarch64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" @@ -5196,10 +4969,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" +name = "windows_i686_gnu" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" @@ -5207,12 +4980,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -5220,10 +4987,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" +name = "windows_i686_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" @@ -5232,10 +4999,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_i686_msvc" -version = "0.53.1" +name = "windows_x86_64_gnu" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" @@ -5244,10 +5011,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" +name = "windows_x86_64_gnullvm" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" @@ -5256,10 +5023,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" +name = "windows_x86_64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" @@ -5267,12 +5034,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.7.15" @@ -5299,17 +5060,17 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "wmi" -version = "0.14.5" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7787dacdd8e71cbc104658aade4009300777f9b5fda6a75f19145fedb8a18e71" +checksum = "7c81b85c57a57500e56669586496bf2abd5cf082b9d32995251185d105208b64" dependencies = [ "chrono", "futures", "log", "serde", "thiserror 2.0.18", - "windows 0.59.0", - "windows-core 0.59.0", + "windows", + "windows-core", ] [[package]] @@ -5339,9 +5100,9 @@ dependencies = [ [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ "asn1-rs", "data-encoding", @@ -5349,8 +5110,9 @@ dependencies = [ "lazy_static", "nom", "oid-registry", + "ring", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.18", "time", ] @@ -5371,10 +5133,11 @@ dependencies = [ [[package]] name = "yasna" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" dependencies = [ + "bit-vec 0.9.1", "time", ] @@ -5401,12 +5164,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "z32" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f" - [[package]] name = "zbus" version = "5.17.0" @@ -5509,6 +5266,20 @@ name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] [[package]] name = "zerotrie" diff --git a/Cargo.toml b/Cargo.toml index 1a2fa67..12ae194 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,10 @@ rust-version = "1.85" [workspace.dependencies] varde-proto = { path = "varde-proto" } -# Pinned per spec: 0.35 is the recommended production line of iroh-blobs; -# the post-0.35 rewrite is not yet production quality. -iroh-blobs = "=0.35.0" -iroh = "0.35" -iroh-io = "0.6" +# iroh 1.0 (June 2026) and the post-rewrite iroh-blobs line, which is +# now the production line (the 0.35 pin's rationale expired with 1.0). +iroh-blobs = "0.103" +iroh = { version = "1", features = ["tls-ring"] } reflink-copy = "0.1" serde = { version = "1", features = ["derive"] } diff --git a/README.md b/README.md index 838805c..65c846e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A small, boring, distro-packageable Linux daemon that owns a content-addressed blob store and mirrors content between consenting -peers, built on [iroh](https://iroh.computer) (iroh-blobs 0.35). +peers, built on [iroh](https://iroh.computer) (iroh 1.0, iroh-blobs 0.103). Applications talk to it over a unix socket: "add this path", "pin this hash", "materialize hash X at path Y". Think: what Windows Delivery Optimization is for updates — generalized, open, legible. diff --git a/SPECS.md b/SPECS.md index 610db95..3b5fb94 100644 --- a/SPECS.md +++ b/SPECS.md @@ -27,8 +27,8 @@ varde/ ``` **Key dependencies and versions:** -- `iroh-blobs = "0.35"` — pin this. Per upstream, the post-0.35 rewrite is not yet production quality; 0.35 is the recommended production line. Use its persistent fs store (`iroh_blobs::store::fs`). -- `iroh` — matching version compatible with iroh-blobs 0.35. +- `iroh-blobs = "0.103"` — the post-rewrite line, now the production line (the old 0.35 pin predated iroh 1.0). Use its persistent fs store (`iroh_blobs::store::fs`). +- `iroh = "1"` — iroh 1.0, stable protocol and API. - `tokio`, `serde`, `serde_json`, `tracing`, `clap` (ctl only), `anyhow`/`thiserror`. - `zbus` for NetworkManager metered-status (feature-gated, `default-features` on Linux only). diff --git a/varde-ctl/tests/roundtrip.rs b/varde-ctl/tests/roundtrip.rs index bdbb9f3..4adc909 100644 --- a/varde-ctl/tests/roundtrip.rs +++ b/varde-ctl/tests/roundtrip.rs @@ -18,6 +18,7 @@ fn ctl_status_round_trips() { max_download_bytes_per_sec: 0, discovery: false, wan_upload: false, + gc_interval_secs: 300, }; let rt = tokio::runtime::Builder::new_multi_thread() diff --git a/varde-daemon/Cargo.toml b/varde-daemon/Cargo.toml index da5e962..9ba7d10 100644 --- a/varde-daemon/Cargo.toml +++ b/varde-daemon/Cargo.toml @@ -14,22 +14,20 @@ required-features = ["socket-api"] [dependencies] varde-proto = { workspace = true } -iroh = { workspace = true, features = ["discovery-local-network"] } +iroh = { workspace = true } iroh-blobs = { workspace = true } -rand = "0.8" -# The next three exist to interoperate with iroh-blobs trait signatures -# and channels; all are already in the dependency tree via iroh. +# mDNS/local-network address lookup left iroh core in 1.0. +iroh-mdns-address-lookup = "0.4" +# Interop with iroh-blobs streams and channels; both are already in the +# dependency tree via iroh-blobs. n0-future = "0.1" -async-channel = "2" -futures-lite = "2" +irpc = "0.17" bytes = "1" # Feature-gated D-Bus client for NetworkManager metered status. zbus = { version = "5", optional = true, default-features = false, features = ["tokio"] } -# Announcement signatures: same ed25519 implementation iroh keys use, -# postcard is the deterministic encoding signed over. -ed25519-dalek = "2" +# Announcement signatures use iroh's own key types; postcard is the +# deterministic encoding signed over. postcard = { version = "1", features = ["use-std"] } -iroh-io = { workspace = true } reflink-copy = { workspace = true } anyhow = { workspace = true } serde = { workspace = true } diff --git a/varde-daemon/src/config.rs b/varde-daemon/src/config.rs index d189768..a43c004 100644 --- a/varde-daemon/src/config.rs +++ b/varde-daemon/src/config.rs @@ -24,6 +24,10 @@ pub struct Config { /// Whether any WAN (non-link-local) upload is permitted. Default off: /// LAN-only posture with zero WAN upload. pub wan_upload: bool, + /// Interval of the store's built-in garbage collector in seconds. + /// Since iroh-blobs 0.103 there is no on-demand gc; unpinned blobs + /// are swept by this loop. + pub gc_interval_secs: u64, } /// Serde image of the TOML config file. Everything optional so an empty @@ -37,6 +41,7 @@ struct FileConfig { max_download_bytes_per_sec: Option, discovery: Option, wan_upload: Option, + gc_interval_secs: Option, } /// Values collected from CLI flags; `None` means "not given". @@ -171,6 +176,9 @@ impl Config { wan_upload: env_bool("VARDE_WAN_UPLOAD")? .or(file.wan_upload) .unwrap_or(false), + gc_interval_secs: env_u64("VARDE_GC_INTERVAL")? + .or(file.gc_interval_secs) + .unwrap_or(300), }) } diff --git a/varde-daemon/src/daemon.rs b/varde-daemon/src/daemon.rs index 68f3114..33ddac9 100644 --- a/varde-daemon/src/daemon.rs +++ b/varde-daemon/src/daemon.rs @@ -51,8 +51,30 @@ impl Daemon { pub async fn open(config: Config) -> anyhow::Result> { std::fs::create_dir_all(&config.store_dir) .with_context(|| format!("creating store directory {}", config.store_dir.display()))?; - let store = BlobStore::open(&config.store_dir).await?; let meta = Arc::new(Meta::load(&config.store_dir)?); + // The store's built-in gc keeps whatever this snapshot reports + // (plus tags and in-flight temp tags) on every run. + let gc_roots: crate::store::GcRootsFn = { + let meta = meta.clone(); + Arc::new(move || { + meta.pins() + .into_iter() + .filter_map(|(hex, _)| { + let hash = Hash::from_str(&hex).ok()?; + Some(HashAndFormat { + hash, + format: blob_format(meta.format_of(&hex)), + }) + }) + .collect() + }) + }; + let store = BlobStore::open( + &config.store_dir, + Duration::from_secs(config.gc_interval_secs.max(1)), + gc_roots, + ) + .await?; // Capacity bounds memory if a subscriber stalls; laggards get a // Lagged error, not unbounded buffering. let (events, _) = broadcast::channel(1024); @@ -68,7 +90,6 @@ impl Daemon { &store, meta.clone(), open_filter, - store.pool_handle(), events.clone(), metered, ) @@ -194,7 +215,7 @@ impl Daemon { /// Track presence for a discovery sighting of `node_id`. Content /// sync happens via the announcement path, not here. - fn on_peer_seen(&self, node_id: iroh::NodeId) { + fn on_peer_seen(&self, node_id: iroh::EndpointId) { let id = node_id.to_string(); let rejoined = { let mut peers = self.lan_peers.lock().expect("lan peers lock"); @@ -247,10 +268,10 @@ impl Daemon { if let Ok((_, _, true)) = self.store.presence(root).await { return; // already complete } - let providers: Vec = ann + let providers: Vec = ann .providers .iter() - .filter(|p| self.meta.is_trusted(&p.node_id.to_string())) + .filter(|p| self.meta.is_trusted(&p.id.to_string())) .cloned() .collect(); if providers.is_empty() { @@ -269,7 +290,7 @@ impl Daemon { /// Queue fetches for every incomplete pin from a trusted LAN peer. /// The downloader dedupes by content, so repeated sightings are /// cheap; discovery resolves the peer's addresses. - async fn sync_pins_from(&self, node_id: iroh::NodeId) { + async fn sync_pins_from(&self, node_id: iroh::EndpointId) { for (hex, _record) in self.meta.pins() { let Ok(hash) = Hash::from_str(&hex) else { continue; @@ -283,7 +304,7 @@ impl Daemon { hash, format: blob_format(self.meta.format_of(&hex)), }, - vec![iroh::NodeAddr::new(node_id)], + vec![iroh::EndpointAddr::from(node_id)], ); } Err(e) => warn!(hash = %hex, error = %e, "checking pin presence"), @@ -334,11 +355,11 @@ impl Daemon { // Fetch if absent: try every trusted peer currently // present on the LAN. if let Ok((_, _, false)) = self.store.presence(parsed).await { - let present: Vec = self + let present: Vec = self .present_trusted_peers() .into_iter() .filter(|p| p.connected) - .filter_map(|p| p.node_id.parse().ok().map(iroh::NodeAddr::new)) + .filter_map(|p| p.node_id.parse::().ok().map(iroh::EndpointAddr::from)) .collect(); if !present.is_empty() { self.transfer.spawn_fetch( @@ -414,9 +435,14 @@ impl Daemon { Ok(ResponseData::Pins { pins }) } Request::Gc {} => { - let roots = self.pin_roots()?; - let blobs_removed = self.store.gc(roots).await?; - Ok(ResponseData::GcDone { blobs_removed }) + // iroh-blobs 0.103 removed on-demand gc: the store runs + // its own periodic mark-and-sweep, protecting pins via + // the roots snapshot handed to BlobStore::open. + Err(OpError::Unimplemented( + "gc now runs continuously inside the blob store; \ + on-demand gc has no API in iroh-blobs 0.103" + .to_string(), + )) } Request::TicketExport { hash } => { let parsed = parse_hash(&hash)?; @@ -458,7 +484,7 @@ impl Daemon { }) } Request::PeerTrust { node_id } => { - let parsed: iroh::NodeId = node_id + let parsed: iroh::EndpointId = node_id .parse() .map_err(|e| OpError::InvalidArgument(format!("invalid node id: {e}")))?; self.meta.trust_peer(&parsed.to_string())?; @@ -476,7 +502,7 @@ impl Daemon { Ok(ResponseData::Done {}) } Request::PeerUntrust { node_id } => { - let parsed: iroh::NodeId = node_id + let parsed: iroh::EndpointId = node_id .parse() .map_err(|e| OpError::InvalidArgument(format!("invalid node id: {e}")))?; if !self.meta.untrust_peer(&parsed.to_string())? { @@ -491,18 +517,6 @@ impl Daemon { } } - /// The GC roots: every pinned hash with its recorded format. - fn pin_roots(&self) -> Result, OpError> { - let mut roots = Vec::new(); - for (hash, _record) in self.meta.pins() { - let parsed = parse_hash(&hash)?; - roots.push(HashAndFormat { - hash: parsed, - format: blob_format(self.meta.format_of(&hash)), - }); - } - Ok(roots) - } } fn blob_format(format: StoredFormat) -> BlobFormat { diff --git a/varde-daemon/src/discovery.rs b/varde-daemon/src/discovery.rs index d7ac51f..98b8683 100644 --- a/varde-daemon/src/discovery.rs +++ b/varde-daemon/src/discovery.rs @@ -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, /// Peers believed to hold the content. - pub providers: Vec, + pub providers: Vec, } /// 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> { - let provider_ids: Vec = announcement.providers.iter().map(|p| p.node_id).collect(); + let provider_ids: Vec = 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>>, + sightings: std::sync::Mutex>>, /// Snapshot of locally pinned roots, queried per sighting. pins: Arc Vec + Send + Sync>, } @@ -135,7 +135,7 @@ pub struct LanDiscovery { impl LanDiscovery { pub fn new( secret: SecretKey, - sightings: mpsc::Receiver, + sightings: mpsc::Receiver, pins: Arc Vec + 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())], } } diff --git a/varde-daemon/src/shaped.rs b/varde-daemon/src/shaped.rs index 4fa4f15..95b8371 100644 --- a/varde-daemon/src/shaped.rs +++ b/varde-daemon/src/shaped.rs @@ -1,29 +1,31 @@ -//! Traffic shaping and per-hash gating for the blob store. +//! Traffic shaping and per-hash gating for the blob provider. //! -//! [`ShapedStore`] wraps the iroh-blobs fs store and implements the full -//! `Store` trait, adding two token buckets: reads of entry data (the -//! bytes a provider sends to peers) draw from the upload bucket, batch -//! writes of downloaded data draw from the download bucket. An optional -//! filter hides hashes from `get`, which is how untrusted peers are -//! limited to openly-served content — the provider simply answers "not -//! found" for everything else. +//! iroh-blobs 0.103 replaced wrappable store traits with a provider +//! event system, so shaping moved from the store to the event seam: +//! [`provider_events`] spawns a handler that intercepts incoming +//! connections and get requests (trust gating: untrusted peers may only +//! fetch openly-served hashes), throttles upload bytes through a token +//! bucket, and forwards transfer progress into the daemon event stream. +//! +//! Download rate limiting rode on the old store's batch writer and has +//! no equivalent seam in 0.103's downloader; `max_download_bytes_per_sec` +//! is currently not enforced (see the migration commit). -use std::future::Future; -use std::io; -use std::path::PathBuf; +use std::collections::HashMap; use std::sync::Arc; use std::time::{Duration, Instant}; -use iroh_blobs::store::bao_tree::io::fsm::{BaoContentItem, Outboard}; -use iroh_blobs::store::fs::Store as FsStore; -use iroh_blobs::store::{ - BaoBatchWriter, ConsistencyCheckProgress, DbIter, EntryStatus, ExportMode, ExportProgressCb, - ImportMode, ImportProgress, Map, MapEntry, MapEntryMut, MapMut, ReadableStore, Store, +use iroh_blobs::provider::events::{ + AbortReason, ClientConnected, ConnectMode, EventMask, EventSender, ObserveMode, + ProviderMessage, RequestMode, ThrottleMode, }; -use iroh_blobs::util::progress::{BoxedProgressSender, IdGenerator, ProgressSender}; -use iroh_blobs::util::Tag; -use iroh_blobs::{BlobFormat, Hash, HashAndFormat, TempTag}; -use iroh_io::AsyncSliceReader; +use iroh_blobs::Hash; +use tokio::sync::broadcast; +use tracing::debug; +use varde_proto::{Direction, Event}; + +use crate::meta::Meta; +use crate::metered::MeteredState; /// An async token bucket. Rate 0 means unlimited. #[derive(Debug)] @@ -81,332 +83,162 @@ impl TokenBucket { } } -/// Predicate deciding whether a hash may be served on this store view. +/// Predicate deciding whether a hash may be served to untrusted peers. pub type ServeFilter = Arc bool + Send + Sync>; -/// The fs store wrapped with rate limiting and an optional serve filter. -#[derive(Clone)] -pub struct ShapedStore { - inner: FsStore, - upload: Arc, - download: Arc, - filter: Option, +/// Provider gate configuration. +pub struct Gate { + pub meta: Arc, + pub open_filter: ServeFilter, + pub upload: Arc, + pub serving_enabled: bool, + pub metered: MeteredState, + pub events: broadcast::Sender, } -impl std::fmt::Debug for ShapedStore { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ShapedStore") - .field("inner", &self.inner) - .field("upload", &self.upload) - .field("download", &self.download) - .field("filtered", &self.filter.is_some()) - .finish() - } -} - -impl ShapedStore { - pub fn new( - inner: FsStore, - upload: Arc, - download: Arc, - ) -> ShapedStore { - ShapedStore { - inner, - upload, - download, - filter: None, - } - } - - /// A view of the same store that only serves hashes passing `filter`. - pub fn filtered(&self, filter: ServeFilter) -> ShapedStore { - ShapedStore { - inner: self.inner.clone(), - upload: self.upload.clone(), - download: self.download.clone(), - filter: Some(filter), - } - } -} - -/// An entry whose data reads draw from the upload bucket. -#[derive(Debug, Clone)] -pub struct ShapedEntry { - inner: ::Entry, - upload: Arc, -} - -impl MapEntry for ShapedEntry { - fn hash(&self) -> Hash { - self.inner.hash() - } - - fn size(&self) -> iroh_blobs::store::BaoBlobSize { - self.inner.size() - } - - fn is_complete(&self) -> bool { - self.inner.is_complete() - } - - async fn outboard(&self) -> io::Result { - // The fs entry's inherent (synchronous) methods shadow the trait - // methods here and below. - self.inner.outboard() - } - - async fn data_reader(&self) -> io::Result { - let inner = self.inner.data_reader(); - Ok(ThrottledReader { - inner, - bucket: self.upload.clone(), - }) - } -} - -/// AsyncSliceReader that pays for bytes read from the upload bucket. -#[derive(Debug)] -struct ThrottledReader { - inner: R, - bucket: Arc, -} - -impl AsyncSliceReader for ThrottledReader { - async fn read_at(&mut self, offset: u64, len: usize) -> io::Result { - let bytes = self.inner.read_at(offset, len).await?; - self.bucket.acquire(bytes.len()).await; - Ok(bytes) - } - - async fn size(&mut self) -> io::Result { - self.inner.size().await - } -} - -impl Map for ShapedStore { - type Entry = ShapedEntry; - - async fn get(&self, hash: &Hash) -> io::Result> { - if let Some(filter) = &self.filter { - if !filter(hash) { - return Ok(None); +/// Spawn the provider event handler and return the [`EventSender`] to +/// wire into [`iroh_blobs::BlobsProtocol`]. +pub fn provider_events(gate: Gate) -> EventSender { + let mask = EventMask { + connected: ConnectMode::Intercept, + get: RequestMode::InterceptLog, + get_many: RequestMode::InterceptLog, + push: RequestMode::Disabled, + observe: ObserveMode::Intercept, + throttle: ThrottleMode::Intercept, + }; + let (sender, mut rx) = EventSender::channel(32, mask); + tokio::spawn(async move { + // Trust decided once per connection, consulted per request. + let mut trusted_conns: HashMap = HashMap::new(); + while let Some(msg) = rx.recv().await { + match msg { + ProviderMessage::ClientConnected(m) => { + let allowed = gate.serving_enabled && !gate.metered.is_metered(); + let trusted = m + .inner + .endpoint_id + .map(|id| gate.meta.is_trusted(&id.to_string())) + .unwrap_or(false); + let ClientConnected { + connection_id, + endpoint_id, + } = m.inner; + debug!(?endpoint_id, trusted, allowed, "incoming blobs connection"); + if allowed { + trusted_conns.insert(connection_id, trusted); + } + let verdict = if allowed { + Ok(()) + } else { + Err(AbortReason::Permission) + }; + m.tx.send(verdict).await.ok(); + } + ProviderMessage::ConnectionClosed(m) => { + trusted_conns.remove(&m.inner.connection_id); + } + ProviderMessage::GetRequestReceived(m) => { + let allowed = allow(&gate, &trusted_conns, m.inner.connection_id, [ + m.inner.request.hash, + ]); + let verdict = if allowed { + Ok(()) + } else { + Err(AbortReason::Permission) + }; + m.tx.send(verdict).await.ok(); + if allowed { + forward_progress(m.rx, gate.events.clone()); + } + } + ProviderMessage::GetManyRequestReceived(m) => { + let allowed = allow( + &gate, + &trusted_conns, + m.inner.connection_id, + m.inner.request.hashes.iter().copied(), + ); + let verdict = if allowed { + Ok(()) + } else { + Err(AbortReason::Permission) + }; + m.tx.send(verdict).await.ok(); + if allowed { + forward_progress(m.rx, gate.events.clone()); + } + } + ProviderMessage::ObserveRequestReceived(m) => { + // Presence is information too: gate it like data. + let allowed = allow(&gate, &trusted_conns, m.inner.connection_id, [ + m.inner.request.hash, + ]); + let verdict = if allowed { + Ok(()) + } else { + Err(AbortReason::Permission) + }; + m.tx.send(verdict).await.ok(); + } + ProviderMessage::Throttle(m) => { + // Pay for the chunk from the shared upload bucket off + // the handler loop, so a deep debt doesn't stall + // unrelated connections' gating decisions. + let bucket = gate.upload.clone(); + tokio::spawn(async move { + bucket.acquire(m.inner.size as usize).await; + m.tx.send(Ok(())).await.ok(); + }); + } + // Push is disabled in the mask; notify variants are not + // subscribed. Ignore anything else. + _ => {} } } - Ok(self.inner.get(hash).await?.map(|inner| ShapedEntry { - inner, - upload: self.upload.clone(), - })) - } + }); + sender } -/// A mutable entry whose batch writes draw from the download bucket. -#[derive(Debug, Clone)] -pub struct ShapedEntryMut { - inner: ::EntryMut, - upload: Arc, - download: Arc, +/// A request is allowed if the connection is trusted, or every requested +/// hash is openly served. +fn allow( + gate: &Gate, + trusted_conns: &HashMap, + connection_id: u64, + hashes: impl IntoIterator, +) -> bool { + if trusted_conns.get(&connection_id).copied().unwrap_or(false) { + return true; + } + hashes.into_iter().all(|hash| (gate.open_filter)(&hash)) } -impl MapEntry for ShapedEntryMut { - fn hash(&self) -> Hash { - self.inner.hash() - } - - fn size(&self) -> iroh_blobs::store::BaoBlobSize { - self.inner.size() - } - - fn is_complete(&self) -> bool { - self.inner.is_complete() - } - - async fn outboard(&self) -> io::Result { - // The fs entry's inherent (synchronous) methods shadow the trait - // methods here and below. - self.inner.outboard() - } - - async fn data_reader(&self) -> io::Result { - let inner = self.inner.data_reader(); - Ok(ThrottledReader { - inner, - bucket: self.upload.clone(), - }) - } -} - -impl MapEntryMut for ShapedEntryMut { - async fn batch_writer(&self) -> io::Result { - let inner = self.inner.batch_writer().await?; - Ok(ThrottledBatchWriter { - inner, - bucket: self.download.clone(), - }) - } -} - -/// BaoBatchWriter that pays for leaf bytes written from the download -/// bucket. -struct ThrottledBatchWriter { - inner: W, - bucket: Arc, -} - -impl BaoBatchWriter for ThrottledBatchWriter { - async fn write_batch(&mut self, size: u64, batch: Vec) -> io::Result<()> { - let bytes: usize = batch - .iter() - .map(|item| match item { - BaoContentItem::Leaf(leaf) => leaf.data.len(), - // Parent nodes are two hashes of overhead. - BaoContentItem::Parent(_) => 64, - }) - .sum(); - self.bucket.acquire(bytes).await; - self.inner.write_batch(size, batch).await - } - - async fn sync(&mut self) -> io::Result<()> { - self.inner.sync().await - } -} - -impl MapMut for ShapedStore { - type EntryMut = ShapedEntryMut; - - async fn get_mut(&self, hash: &Hash) -> io::Result> { - Ok(self.inner.get_mut(hash).await?.map(|inner| ShapedEntryMut { - inner, - upload: self.upload.clone(), - download: self.download.clone(), - })) - } - - async fn get_or_create(&self, hash: Hash, size: u64) -> io::Result { - let inner = self.inner.get_or_create(hash, size).await?; - Ok(ShapedEntryMut { - inner, - upload: self.upload.clone(), - download: self.download.clone(), - }) - } - - async fn entry_status(&self, hash: &Hash) -> io::Result { - self.inner.entry_status(hash).await - } - - fn entry_status_sync(&self, hash: &Hash) -> io::Result { - self.inner.entry_status_sync(hash) - } - - async fn insert_complete(&self, entry: ShapedEntryMut) -> io::Result<()> { - self.inner.insert_complete(entry.inner).await - } -} - -impl ReadableStore for ShapedStore { - async fn blobs(&self) -> io::Result> { - self.inner.blobs().await - } - - async fn tags( - &self, - from: Option, - to: Option, - ) -> io::Result> { - self.inner.tags(from, to).await - } - - fn temp_tags(&self) -> Box + Send + Sync + 'static> { - self.inner.temp_tags() - } - - async fn consistency_check( - &self, - repair: bool, - tx: BoxedProgressSender, - ) -> io::Result<()> { - self.inner.consistency_check(repair, tx).await - } - - async fn partial_blobs(&self) -> io::Result> { - self.inner.partial_blobs().await - } - - async fn export( - &self, - hash: Hash, - target: PathBuf, - mode: ExportMode, - progress: ExportProgressCb, - ) -> io::Result<()> { - self.inner.export(hash, target, mode, progress).await - } -} - -impl Store for ShapedStore { - async fn import_file( - &self, - data: PathBuf, - mode: ImportMode, - format: BlobFormat, - progress: impl ProgressSender + IdGenerator, - ) -> io::Result<(TempTag, u64)> { - self.inner.import_file(data, mode, format, progress).await - } - - async fn import_bytes(&self, bytes: bytes::Bytes, format: BlobFormat) -> io::Result { - self.inner.import_bytes(bytes, format).await - } - - async fn import_stream( - &self, - data: impl futures_lite::Stream> + Send + Unpin + 'static, - format: BlobFormat, - progress: impl ProgressSender + IdGenerator, - ) -> io::Result<(TempTag, u64)> { - self.inner.import_stream(data, format, progress).await - } - - async fn set_tag(&self, name: Tag, hash: HashAndFormat) -> io::Result<()> { - self.inner.set_tag(name, hash).await - } - - async fn rename_tag(&self, from: Tag, to: Tag) -> io::Result<()> { - self.inner.rename_tag(from, to).await - } - - async fn delete_tags(&self, from: Option, to: Option) -> io::Result<()> { - self.inner.delete_tags(from, to).await - } - - async fn create_tag(&self, hash: HashAndFormat) -> io::Result { - self.inner.create_tag(hash).await - } - - fn temp_tag(&self, value: HashAndFormat) -> TempTag { - self.inner.temp_tag(value) - } - - async fn gc_run(&self, config: iroh_blobs::store::GcConfig, protected_cb: G) - where - G: Fn() -> Gut, - Gut: Future> + Send, - { - self.inner.gc_run(config, protected_cb).await - } - - async fn delete(&self, hashes: Vec) -> io::Result<()> { - self.inner.delete(hashes).await - } - - async fn shutdown(&self) { - self.inner.shutdown().await - } - - async fn sync(&self) -> io::Result<()> { - self.inner.sync().await - } +/// Forward per-request transfer updates into the daemon event stream. +fn forward_progress( + mut rx: irpc::channel::mpsc::Receiver, + events: broadcast::Sender, +) { + use iroh_blobs::provider::events::RequestUpdate; + tokio::spawn(async move { + let mut current: Option<(Hash, u64)> = None; + while let Ok(Some(update)) = rx.recv().await { + match update { + RequestUpdate::Started(s) => current = Some((s.hash, s.size)), + RequestUpdate::Progress(p) => { + if let Some((hash, size)) = ¤t { + let _ = events.send(Event::TransferProgress { + hash: hash.to_hex().to_string(), + direction: Direction::Upload, + bytes_done: p.end_offset, + bytes_total: Some(*size), + }); + } + } + RequestUpdate::Completed(_) | RequestUpdate::Aborted(_) => break, + } + } + }); } #[cfg(test)] diff --git a/varde-daemon/src/store.rs b/varde-daemon/src/store.rs index c64af6c..f965fa2 100644 --- a/varde-daemon/src/store.rs +++ b/varde-daemon/src/store.rs @@ -1,24 +1,27 @@ //! Blob store operations on top of the iroh-blobs persistent fs store. -use std::collections::BTreeSet; +use std::collections::HashSet; use std::path::{Path, PathBuf}; +use std::sync::{Arc, OnceLock}; +use std::time::Duration; use anyhow::Context; +use iroh_blobs::api::blobs::{AddPathOptions, BlobStatus, ImportMode}; use iroh_blobs::format::collection::Collection; use iroh_blobs::hashseq::HashSeq; -use iroh_blobs::store::{ - EntryStatus, ImportMode, Map, MapEntry, MapMut, ReadableStore, Store as _, -}; -use iroh_blobs::util::local_pool::{LocalPool, LocalPoolHandle}; -use iroh_blobs::util::progress::IgnoreProgressSender; +use iroh_blobs::store::fs::options::{Options, PathOptions}; +use iroh_blobs::store::fs::FsStore; +use iroh_blobs::store::{GcConfig, ProtectCb, ProtectOutcome}; use iroh_blobs::{BlobFormat, Hash, HashAndFormat}; -use iroh_io::{AsyncSliceReader, AsyncSliceReaderExt}; -use tokio::io::AsyncWriteExt; -use tracing::{debug, info}; +use tracing::{debug, info, warn}; use varde_proto::MaterializeMode; use crate::meta::StoredFormat; +/// Snapshot of the gc roots (the pinned hashes with their formats), +/// consulted by the store's gc before every run. +pub type GcRootsFn = Arc Vec + Send + Sync>; + /// Operation errors that map onto protocol error codes. #[derive(Debug, thiserror::Error)] pub enum OpError { @@ -34,64 +37,102 @@ pub enum OpError { Unimplemented(String), } -/// The daemon's blob store: an iroh-blobs fs store rooted at -/// `/blobs`. -/// -/// Reads from store entries yield non-`Send` futures, so those operations -/// run on a dedicated [`LocalPool`] — the same pattern iroh-blobs itself -/// uses for its provider and GC tasks. -#[derive(Debug, Clone)] -pub struct BlobStore { - store: iroh_blobs::store::fs::Store, - data_dir: PathBuf, - pool: LocalPoolHandle, - // Owns the pool threads; dropped when the last clone goes away. - _pool: std::sync::Arc, +/// Wrap an iroh-blobs API error as an internal error. +fn internal(e: impl std::error::Error + Send + Sync + 'static) -> OpError { + OpError::Internal(anyhow::Error::new(e)) } -/// Reading a blob entry for a streaming copy happens in chunks this size. -const COPY_CHUNK: u64 = 1024 * 1024; +/// The daemon's blob store: an iroh-blobs fs store rooted at +/// `/blobs`. +#[derive(Debug, Clone)] +pub struct BlobStore { + store: FsStore, + data_dir: PathBuf, +} impl BlobStore { - pub async fn open(store_dir: &Path) -> anyhow::Result { + /// Open the store. `gc_roots` supplies the pinned hashes the built-in + /// garbage collector must keep (temp tags and stored tags are + /// protected by the store itself); their hashseq children are + /// expanded here before every run. + pub async fn open( + store_dir: &Path, + gc_interval: Duration, + gc_roots: GcRootsFn, + ) -> anyhow::Result { let blobs_dir = store_dir.join("blobs"); - let store = iroh_blobs::store::fs::Store::load(&blobs_dir) + // The protect callback needs the store API to expand hashseq + // roots, but it is installed before the store exists — hence the + // cell, filled right after load. + let store_cell: Arc> = Arc::new(OnceLock::new()); + let protect: ProtectCb = { + let cell = store_cell.clone(); + Arc::new(move |live: &mut HashSet| { + let cell = cell.clone(); + let roots = gc_roots(); + // The callback future must be Sync; the store API's + // futures are not, so the expansion runs on its own task. + Box::pin(async move { + let expanded = tokio::spawn(async move { + let mut hashes: Vec = Vec::new(); + for HashAndFormat { hash, format } in roots { + hashes.push(hash); + if format.is_raw() { + continue; + } + let Some(store) = cell.get() else { continue }; + match children_of(store, hash).await { + Ok(children) => hashes.extend(children), + Err(e) => { + warn!(hash = %hash.to_hex(), error = %e, "gc protect: expanding hashseq"); + return None; + } + } + } + Some(hashes) + }) + .await; + match expanded { + Ok(Some(hashes)) => { + live.extend(hashes); + ProtectOutcome::Continue + } + // Confused about liveness: skip this run rather + // than sweep blobs that should be protected. + Ok(None) => ProtectOutcome::Abort, + Err(e) => { + warn!(error = %e, "gc protect task failed"); + ProtectOutcome::Abort + } + } + }) + }) + }; + let options = Options { + path: PathOptions::new(&blobs_dir), + inline: Default::default(), + batch: Default::default(), + gc: Some(GcConfig { + interval: gc_interval, + add_protected: Some(protect), + }), + }; + let store = FsStore::load_with_opts(blobs_dir.join("blobs.db"), options) .await .with_context(|| format!("opening blob store at {}", blobs_dir.display()))?; - let pool = LocalPool::default(); + let _ = store_cell.set((*store).clone()); Ok(BlobStore { store, data_dir: blobs_dir.join("data"), - pool: pool.handle().clone(), - _pool: std::sync::Arc::new(pool), }) } - /// Run a non-`Send` store operation on the local pool. - async fn on_pool(&self, f: F) -> Result - where - F: FnOnce(BlobStore) -> Fut + Send + 'static, - Fut: std::future::Future> + 'static, - T: Send + 'static, - { - let this = self.clone(); - self.pool - .spawn(move || f(this)) - .await - .map_err(|e| OpError::Internal(anyhow::anyhow!("local pool: {e}")))? - } - - /// Access to the underlying iroh-blobs store (used by the transfer - /// layer). - pub fn inner(&self) -> &iroh_blobs::store::fs::Store { + /// Access to the underlying iroh-blobs store API (used by the + /// transfer layer). `FsStore` derefs to the API handle. + pub fn api(&self) -> &iroh_blobs::api::Store { &self.store } - /// The local pool the transfer layer shares for non-`Send` blob work. - pub fn pool_handle(&self) -> LocalPoolHandle { - self.pool.clone() - } - /// Import a file or directory. Returns the root hash, total imported /// bytes, and the resulting format (`Raw` for files, `HashSeq` for /// directories). @@ -110,7 +151,7 @@ impl BlobStore { if meta.is_file() { let (tag, size) = self.import_one(path.to_owned()).await?; info!(hash = %tag.hash().to_hex(), size, "imported file"); - return Ok((*tag.hash(), size, StoredFormat::Raw)); + return Ok((tag.hash(), size, StoredFormat::Raw)); } if !meta.is_dir() { return Err(OpError::InvalidArgument(format!( @@ -145,27 +186,40 @@ impl BlobStore { } let collection: Collection = children .iter() - .map(|(name, tag)| (name.clone(), *tag.hash())) + .map(|(name, tag)| (name.clone(), tag.hash())) .collect(); let root_tag = collection .store(&self.store) .await .context("storing collection")?; - let root = *root_tag.hash(); + let root = root_tag.hash(); info!(hash = %root.to_hex(), files = children.len(), total, "imported directory"); Ok((root, total, StoredFormat::HashSeq)) } - async fn import_one(&self, path: PathBuf) -> Result<(iroh_blobs::TempTag, u64), OpError> { - let (tag, size) = self + async fn import_one( + &self, + path: PathBuf, + ) -> Result<(iroh_blobs::api::TempTag, u64), OpError> { + let tag = self .store - .import_file( + .add_path_with_opts(AddPathOptions { path, - ImportMode::Copy, - BlobFormat::Raw, - IgnoreProgressSender::default(), - ) - .await?; + format: BlobFormat::Raw, + mode: ImportMode::Copy, + }) + .temp_tag() + .await + .map_err(internal)?; + let size = match self.store.blobs().status(tag.hash()).await.map_err(internal)? { + BlobStatus::Complete { size } => size, + _ => { + return Err(OpError::Internal(anyhow::anyhow!( + "freshly imported blob {} is not complete", + tag.hash().to_hex() + ))) + } + }; Ok((tag, size)) } @@ -184,25 +238,11 @@ impl BlobStore { dest.display() ))); } - let dest = dest.to_owned(); - self.on_pool( - move |this| async move { this.materialize_local(hash, format, &dest, mode).await }, - ) - .await - } - - async fn materialize_local( - &self, - hash: Hash, - format: StoredFormat, - dest: &Path, - mode: MaterializeMode, - ) -> Result<(u64, bool), OpError> { let allow_reflink = matches!(mode, MaterializeMode::ReflinkOrCopy); match format { StoredFormat::Raw => self.export_blob(hash, dest, allow_reflink).await, StoredFormat::HashSeq => { - let collection = Collection::load_db(&self.store, &hash) + let collection = Collection::load(hash, self.api()) .await .map_err(|e| OpError::NotFound(format!("loading collection: {e}")))?; let mut total = 0u64; @@ -222,25 +262,30 @@ impl BlobStore { } /// Export one blob. Tries `FICLONE` via reflink first (zero-copy on - /// btrfs/XFS when store and dest share a filesystem), falls back to a - /// streaming copy. Never hardlinks: store files must stay immutable. + /// btrfs/XFS when store and dest share a filesystem), falls back to + /// the store's export (a copy). Never hardlinks: store files must + /// stay immutable. async fn export_blob( &self, hash: Hash, dest: &Path, allow_reflink: bool, ) -> Result<(u64, bool), OpError> { - let entry = - self.store.get(&hash).await?.ok_or_else(|| { - OpError::NotFound(format!("{} is not in the store", hash.to_hex())) - })?; - if !entry.is_complete() { - return Err(OpError::NotFound(format!( - "{} is only partially present", - hash.to_hex() - ))); - } - let size = entry.size().value(); + let size = match self.store.blobs().status(hash).await.map_err(internal)? { + BlobStatus::Complete { size } => size, + BlobStatus::Partial { .. } => { + return Err(OpError::NotFound(format!( + "{} is only partially present", + hash.to_hex() + ))) + } + BlobStatus::NotFound => { + return Err(OpError::NotFound(format!( + "{} is not in the store", + hash.to_hex() + ))) + } + }; if let Some(parent) = dest.parent() { tokio::fs::create_dir_all(parent).await?; } @@ -272,129 +317,52 @@ impl BlobStore { } } - let mut reader = entry.data_reader(); - let mut file = tokio::fs::File::create(dest).await?; - let mut offset = 0u64; - while offset < size { - let len = (size - offset).min(COPY_CHUNK) as usize; - let chunk = reader.read_at(offset, len).await?; - if chunk.is_empty() { - return Err(OpError::Io(std::io::Error::new( - std::io::ErrorKind::UnexpectedEof, - format!("blob {} truncated at {offset}", hash.to_hex()), - ))); - } - file.write_all(&chunk).await?; - offset += chunk.len() as u64; - } - file.flush().await?; - Ok((size, false)) + let bytes = self + .store + .blobs() + .export(hash, dest) + .await + .map_err(internal)?; + Ok((bytes, false)) } /// Presence of `hash`: (have_bytes, total_bytes, complete). pub async fn presence(&self, hash: Hash) -> Result<(u64, Option, bool), OpError> { - match self.store.entry_status(&hash).await? { - EntryStatus::NotFound => Ok((0, None, false)), - EntryStatus::Partial => { - let total = self.store.get(&hash).await?.map(|e| e.size().value()); - // Valid-range accounting for partials arrives with the - // transfer milestone; absence of data is the safe report. - Ok((0, total, false)) - } - EntryStatus::Complete => { - let entry = self - .store - .get(&hash) - .await? - .ok_or_else(|| OpError::NotFound(hash.to_hex().to_string()))?; - let size = entry.size().value(); - Ok((size, Some(size), true)) - } + match self.store.blobs().status(hash).await.map_err(internal)? { + BlobStatus::NotFound => Ok((0, None, false)), + // Valid-range accounting for partials arrives with the + // transfer milestone; absence of data is the safe report. + BlobStatus::Partial { size } => Ok((0, size, false)), + BlobStatus::Complete { size } => Ok((size, Some(size), true)), } } /// The child hashes of a complete HashSeq root (empty for absent or /// partial roots). pub async fn hashseq_children(&self, root: Hash) -> Result, 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. - pub async fn gc(&self, roots: Vec) -> Result { - self.on_pool(move |this| async move { this.gc_local(roots).await }) - .await - } - - async fn gc_local(&self, roots: Vec) -> Result { - let mut live: BTreeSet = BTreeSet::new(); - let mut all_roots = roots; - all_roots.extend(self.store.temp_tags()); - for item in self.store.tags(None, None).await.context(TAGS_CONTEXT)? { - let (_name, haf) = item.context(TAGS_CONTEXT)?; - all_roots.push(haf); - } - - for HashAndFormat { hash, format } in all_roots { - if !live.insert(hash) || format.is_raw() { - continue; - } - // HashSeq root: its children are live too. A partial root - // can't be expanded; its bytes are still protected. - let Some(entry) = self.store.get(&hash).await? else { - continue; - }; - if !entry.is_complete() { - continue; - } - 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}")))?; - live.extend(seq.iter()); - } - - let mut doomed = Vec::new(); - for hash in self - .store - .blobs() - .await? - .chain(self.store.partial_blobs().await?) - { - let hash = hash?; - if !live.contains(&hash) { - doomed.push(hash); - } - } - let removed = doomed.len() as u64; - if !doomed.is_empty() { - self.store.delete(doomed).await?; - } - info!(removed, live = live.len(), "gc done"); - Ok(removed) + children_of(self.api(), root).await } /// Flush and shut down the store actor. pub async fn shutdown(&self) { - self.store.shutdown().await; + if let Err(e) = self.store.shutdown().await { + debug!(error = %e, "store shutdown"); + } } } -const TAGS_CONTEXT: &str = "listing tags"; +/// The child hashes of a complete HashSeq root (empty for absent or +/// partial roots). +async fn children_of(store: &iroh_blobs::api::Store, root: Hash) -> Result, OpError> { + match store.blobs().status(root).await.map_err(internal)? { + BlobStatus::Complete { .. } => {} + _ => return Ok(Vec::new()), + } + let bytes = store.blobs().get_bytes(root).await.map_err(internal)?; + let seq = HashSeq::try_from(bytes) + .map_err(|e| OpError::Internal(anyhow::anyhow!("invalid hashseq: {e}")))?; + Ok(seq.iter().collect()) +} /// Recursively collect regular files under `dir` as (relative-name, path), /// sorted for deterministic collection hashes. Symlinks are followed for diff --git a/varde-daemon/src/transfer.rs b/varde-daemon/src/transfer.rs index a0dba49..fc8bd00 100644 --- a/varde-daemon/src/transfer.rs +++ b/varde-daemon/src/transfer.rs @@ -1,25 +1,20 @@ //! iroh endpoint, blob provider and downloader. //! -//! This module is the transport seam: rate limiting lives in -//! [`crate::shaped::ShapedStore`] wired up here, and a scavenger -//! congestion controller would later slot in at the same place without -//! touching the daemon logic above. +//! This module is the transport seam: trust gating and rate limiting +//! live in [`crate::shaped`]'s provider event handler wired up here, and +//! a scavenger congestion controller would later slot in at the same +//! place without touching the daemon logic above. use std::path::Path; use std::sync::Arc; use anyhow::{Context, Result}; -use iroh::discovery::mdns::MdnsDiscovery; -use iroh::endpoint::Connection; -use iroh::protocol::{ProtocolHandler, Router}; -use iroh::{Endpoint, NodeAddr, NodeId, RelayMode, SecretKey}; -use iroh_blobs::downloader::{DownloadRequest, Downloader}; -use iroh_blobs::get::db::DownloadProgress; -use iroh_blobs::provider::{handle_connection, CustomEventSender, EventSender}; -use iroh_blobs::util::local_pool::LocalPoolHandle; -use iroh_blobs::util::progress::AsyncChannelProgressSender; -use iroh_blobs::{BlobFormat, Hash, HashAndFormat}; -use n0_future::boxed::BoxFuture; +use iroh::address_lookup::memory::MemoryLookup; +use iroh::protocol::Router; +use iroh::{Endpoint, EndpointAddr, EndpointId, RelayMode, SecretKey}; +use iroh_blobs::api::downloader::{DownloadOptions, Downloader, Shuffled, SplitStrategy}; +use iroh_blobs::{BlobFormat, BlobsProtocol, Hash, HashAndFormat}; +use iroh_mdns_address_lookup::{DiscoveryEvent, MdnsAddressLookup}; use n0_future::StreamExt; use tokio::sync::{broadcast, mpsc}; use tracing::{debug, info, warn}; @@ -28,7 +23,7 @@ use varde_proto::{Direction, Event}; use crate::config::Config; use crate::meta::Meta; use crate::metered::MeteredState; -use crate::shaped::{ServeFilter, ShapedStore, TokenBucket}; +use crate::shaped::{Gate, ServeFilter, TokenBucket}; use crate::store::BlobStore; /// The network side of the daemon: one iroh endpoint serving the blob @@ -39,71 +34,13 @@ pub struct Transfer { endpoint: Endpoint, router: Router, downloader: Downloader, + /// Address book for provider addresses learned out-of-band (ticket + /// imports): the downloader dials by endpoint id and resolves + /// addresses through the endpoint's address lookup services. + known_addrs: MemoryLookup, events: broadcast::Sender, metered: MeteredState, - discovery_rx: std::sync::Mutex>>, -} - -/// Serves blob requests with trust gating: trusted peers see the whole -/// store, untrusted peers see only the openly-served subset (and get -/// "not found" for the rest). With serving disabled (upload cap 0) every -/// incoming connection is closed immediately. -#[derive(Debug, Clone)] -struct GatedProvider { - full_view: ShapedStore, - open_view: ShapedStore, - meta: Arc, - events: EventSender, - pool: LocalPoolHandle, - serving_enabled: bool, - metered: MeteredState, -} - -impl ProtocolHandler for GatedProvider { - fn accept(&self, connection: Connection) -> BoxFuture> { - let this = self.clone(); - Box::pin(async move { - let remote = connection.remote_node_id()?; - if !this.serving_enabled || this.metered.is_metered() { - debug!(%remote, "serving disabled or metered, closing connection"); - connection.close(0u32.into(), b"serving disabled"); - return Ok(()); - } - let trusted = this.meta.is_trusted(&remote.to_string()); - debug!(%remote, trusted, "incoming blobs connection"); - if trusted { - handle_connection(connection, this.full_view, this.events, this.pool).await; - } else { - handle_connection(connection, this.open_view, this.events, this.pool).await; - } - Ok(()) - }) - } -} - -/// Forwards provider transfer events into the daemon event stream. -#[derive(Debug)] -struct UploadEvents(broadcast::Sender); - -impl CustomEventSender for UploadEvents { - fn send(&self, event: iroh_blobs::provider::Event) -> BoxFuture<()> { - self.try_send(event); - Box::pin(async {}) - } - - fn try_send(&self, event: iroh_blobs::provider::Event) { - if let iroh_blobs::provider::Event::TransferProgress { - hash, end_offset, .. - } = event - { - let _ = self.0.send(Event::TransferProgress { - hash: hash.to_hex().to_string(), - direction: Direction::Upload, - bytes_done: end_offset, - bytes_total: None, - }); - } - } + discovery_rx: std::sync::Mutex>>, } impl Transfer { @@ -117,60 +54,71 @@ impl Transfer { store: &BlobStore, meta: Arc, open_filter: ServeFilter, - pool: LocalPoolHandle, events: broadcast::Sender, metered: MeteredState, ) -> Result { let secret = load_or_create_secret(&config.store_dir.join("secret.key"))?; - let mut builder = Endpoint::builder().secret_key(secret.clone()); - if !config.wan_upload { - builder = builder.relay_mode(RelayMode::Disabled); - } + // With wan_upload the n0 defaults apply (their relays and DNS + // lookup, matching the pre-1.0 default relay mode); otherwise the + // endpoint gets no external services at all. + let builder = if config.wan_upload { + Endpoint::builder(iroh::endpoint::presets::N0) + } else { + Endpoint::builder(iroh::endpoint::presets::Minimal).relay_mode(RelayMode::Disabled) + }; + let endpoint = builder + .secret_key(secret.clone()) + .bind() + .await + .context("binding iroh endpoint")?; + info!(endpoint_id = %endpoint.id(), discovery = config.discovery, "endpoint up"); + + let known_addrs = MemoryLookup::with_provenance("varde-ticket"); + endpoint + .address_lookup() + .context("endpoint address lookup services")? + .add(known_addrs.clone()); // LAN discovery: advertise under iroh's mDNS-style local // discovery service (identifiable `_iroh` mdns records, not - // anonymous noise). Discovered node ids stream to the daemon, + // anonymous noise). Discovered endpoint ids stream to the daemon, // which decides what to do based on trust. let (discovery_tx, discovery_rx) = mpsc::channel(64); if config.discovery { - let mdns = - MdnsDiscovery::new(secret.public()).context("starting mdns local discovery")?; - if let Some(mut stream) = iroh::discovery::Discovery::subscribe(&mdns) { - tokio::spawn(async move { - while let Some(item) = stream.next().await { - if discovery_tx.send(item.node_id()).await.is_err() { - break; - } + let mdns = MdnsAddressLookup::builder() + .build(endpoint.id()) + .context("starting mdns local discovery")?; + let mut sightings = mdns.subscribe().await; + tokio::spawn(async move { + while let Some(event) = sightings.next().await { + let DiscoveryEvent::Discovered { endpoint_info, .. } = event else { + continue; + }; + if discovery_tx.send(endpoint_info.endpoint_id).await.is_err() { + break; } - }); - } - builder = builder.discovery(Box::new(mdns)); + } + }); + endpoint + .address_lookup() + .context("endpoint address lookup services")? + .add(mdns); } - let endpoint = builder.bind().await.context("binding iroh endpoint")?; - info!(node_id = %endpoint.node_id(), discovery = config.discovery, "endpoint up"); - // Best-effort low-priority marking of our UDP traffic. - let (v4, v6) = endpoint.bound_sockets(); - let bound: Vec = std::iter::once(v4).chain(v6).collect(); - crate::dscp::mark_endpoint_sockets(&bound); + crate::dscp::mark_endpoint_sockets(&endpoint.bound_sockets()); - let upload_bucket = TokenBucket::new(config.max_upload_bytes_per_sec); - let download_bucket = TokenBucket::new(config.max_download_bytes_per_sec); - let shaped = ShapedStore::new(store.inner().clone(), upload_bucket, download_bucket); - - let provider_events = EventSender::new(Some(Arc::new(UploadEvents(events.clone())))); - let provider = GatedProvider { - full_view: shaped.clone(), - open_view: shaped.filtered(open_filter), + let provider_events = crate::shaped::provider_events(Gate { meta, - events: provider_events, - pool: pool.clone(), + open_filter, + upload: TokenBucket::new(config.max_upload_bytes_per_sec), serving_enabled: config.max_upload_bytes_per_sec > 0, metered: metered.clone(), - }; + events: events.clone(), + }); + let provider = BlobsProtocol::new(store.api(), Some(provider_events)); - let downloader = Downloader::new(shaped, endpoint.clone(), pool); + let downloader = store.api().downloader(&endpoint); let router = Router::builder(endpoint.clone()) .accept(iroh_blobs::ALPN, provider) .spawn(); @@ -179,15 +127,16 @@ impl Transfer { endpoint, router, downloader, + known_addrs, events, metered, discovery_rx: std::sync::Mutex::new(Some(discovery_rx)), }) } - /// Our stable node id. + /// Our stable endpoint id. pub fn node_id(&self) -> String { - self.endpoint.node_id().to_string() + self.endpoint.id().to_string() } /// The endpoint's identity key (also signs our announcements). @@ -195,68 +144,89 @@ impl Transfer { self.endpoint.secret_key().clone() } - /// Take the stream of locally discovered node ids. Yields each + /// Take the stream of locally discovered endpoint ids. Yields each /// sighting (mdns re-announces periodically); the daemon dedupes. /// Callable once; returns None afterwards or with discovery off. - pub fn take_discovery(&self) -> Option> { + pub fn take_discovery(&self) -> Option> { self.discovery_rx.lock().expect("discovery lock").take() } /// Produce a ticket for out-of-band sharing of `content`. pub async fn export_ticket(&self, content: HashAndFormat) -> Result { - let addr = self - .endpoint - .node_addr() - .await - .context("waiting for endpoint address")?; - let ticket = iroh_blobs::ticket::BlobTicket::new(addr, content.hash, content.format)?; + let addr = self.endpoint.addr(); + anyhow::ensure!( + !addr.addrs.is_empty(), + "endpoint has no dialable addresses yet" + ); + let ticket = iroh_blobs::ticket::BlobTicket::new(addr, content.hash, content.format); Ok(ticket.to_string()) } /// Queue a background fetch of `content` from `providers`. Emits /// progress events and [`Event::PinComplete`] when fully verified. - pub fn spawn_fetch(&self, content: HashAndFormat, providers: Vec) { + pub fn spawn_fetch(&self, content: HashAndFormat, providers: Vec) { if self.metered.is_metered() { // The pin stays recorded; auto-sync retries once unmetered. info!(hash = %content.hash.to_hex(), "metered connection: fetch deferred"); return; } + // The downloader dials by EndpointId; teach the endpoint any + // direct addresses we know (ticket-embedded ones). Id-only + // provider entries resolve via discovery instead. + let mut ids = Vec::with_capacity(providers.len()); + for provider in providers { + ids.push(provider.id); + if !provider.addrs.is_empty() { + self.known_addrs.add_endpoint_info(provider); + } + } + let downloader = self.downloader.clone(); let events = self.events.clone(); - let endpoint = self.endpoint.clone(); tokio::spawn(async move { - // The downloader dials by NodeId; the endpoint must be taught - // any direct addresses we know (ticket-embedded ones), or the - // dial fails with "no addressing information". Id-only - // provider entries resolve via discovery instead. - for provider in &providers { - if !provider.direct_addresses.is_empty() || provider.relay_url.is_some() { - if let Err(e) = endpoint.add_node_addr(provider.clone()) { - debug!(node = %provider.node_id, error = %e, "adding provider address"); + let progress = downloader.download_with_opts(DownloadOptions::new( + content, + Shuffled::new(ids), + SplitStrategy::None, + )); + let mut stream = match progress.stream().await { + Ok(stream) => stream, + Err(e) => { + warn!(hash = %content.hash.to_hex(), error = %e, "fetch failed to start"); + return; + } + }; + use iroh_blobs::api::downloader::DownloadProgressItem; + let mut failed = false; + while let Some(item) = stream.next().await { + match item { + DownloadProgressItem::Progress(bytes_done) => { + let _ = events.send(Event::TransferProgress { + hash: content.hash.to_hex().to_string(), + direction: Direction::Download, + bytes_done, + bytes_total: None, + }); } + DownloadProgressItem::ProviderFailed { id, .. } => { + debug!(hash = %content.hash.to_hex(), provider = %id, "provider failed"); + } + DownloadProgressItem::Error(e) => { + warn!(hash = %content.hash.to_hex(), error = %e, "fetch failed"); + failed = true; + } + DownloadProgressItem::DownloadError => { + warn!(hash = %content.hash.to_hex(), "fetch failed"); + failed = true; + } + _ => {} } } - - let (progress_tx, progress_rx) = async_channel::bounded(64); - tokio::spawn(forward_download_progress( - content.hash, - progress_rx, - events.clone(), - )); - - let request = DownloadRequest::new(content, providers) - .progress_sender(AsyncChannelProgressSender::new(progress_tx)); - let handle = downloader.queue(request).await; - match handle.await { - Ok(_stats) => { - info!(hash = %content.hash.to_hex(), "fetch complete"); - let _ = events.send(Event::PinComplete { - hash: content.hash.to_hex().to_string(), - }); - } - Err(e) => { - warn!(hash = %content.hash.to_hex(), error = %e, "fetch failed"); - } + if !failed { + info!(hash = %content.hash.to_hex(), "fetch complete"); + let _ = events.send(Event::PinComplete { + hash: content.hash.to_hex().to_string(), + }); } }); } @@ -270,37 +240,12 @@ impl Transfer { } } -/// Translate iroh-blobs download progress into daemon transfer events. -async fn forward_download_progress( - root: Hash, - rx: async_channel::Receiver, - events: broadcast::Sender, -) { - let mut current_total = None; - while let Ok(progress) = rx.recv().await { - match progress { - DownloadProgress::Found { size, .. } => { - current_total = Some(size); - } - DownloadProgress::Progress { offset, .. } => { - let _ = events.send(Event::TransferProgress { - hash: root.to_hex().to_string(), - direction: Direction::Download, - bytes_done: offset, - bytes_total: current_total, - }); - } - DownloadProgress::AllDone(_) | DownloadProgress::Abort(_) => break, - _ => {} - } - } -} - /// Parse a ticket string into (root, format, provider address). -pub fn parse_ticket(ticket: &str) -> Result<(Hash, BlobFormat, NodeAddr), String> { +pub fn parse_ticket(ticket: &str) -> Result<(Hash, BlobFormat, EndpointAddr), String> { let ticket: iroh_blobs::ticket::BlobTicket = ticket.parse().map_err(|e| format!("invalid ticket: {e}"))?; - Ok((ticket.hash(), ticket.format(), ticket.node_addr().clone())) + let (addr, hash, format) = ticket.into_parts(); + Ok((hash, format, addr)) } /// Load the endpoint secret key from `path`, creating it (mode 0600) on @@ -310,7 +255,7 @@ fn load_or_create_secret(path: &Path) -> Result { Ok(hex) => parse_secret(hex.trim()) .with_context(|| format!("parsing secret key {}", path.display())), Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - let secret = SecretKey::generate(rand::rngs::OsRng); + let secret = SecretKey::generate(); let hex = hex_encode(&secret.to_bytes()); use std::io::Write; use std::os::unix::fs::OpenOptionsExt; diff --git a/varde-daemon/tests/lan_trust.rs b/varde-daemon/tests/lan_trust.rs index 1dcb776..4a30fcf 100644 --- a/varde-daemon/tests/lan_trust.rs +++ b/varde-daemon/tests/lan_trust.rs @@ -83,13 +83,8 @@ fn wait_complete(socket: &Path, hash: &str, timeout: Duration) -> bool { fn forge_ticket(real_ticket: &str, target_hash: &str) -> String { let ticket = iroh_blobs::ticket::BlobTicket::from_str(real_ticket).unwrap(); let hash = iroh_blobs::Hash::from_str(target_hash).unwrap(); - iroh_blobs::ticket::BlobTicket::new( - ticket.node_addr().clone(), - hash, - iroh_blobs::BlobFormat::Raw, - ) - .unwrap() - .to_string() + iroh_blobs::ticket::BlobTicket::new(ticket.addr().clone(), hash, iroh_blobs::BlobFormat::Raw) + .to_string() } #[test] diff --git a/varde-daemon/tests/store_ops.rs b/varde-daemon/tests/store_ops.rs index 3d28479..c0ec5c9 100644 --- a/varde-daemon/tests/store_ops.rs +++ b/varde-daemon/tests/store_ops.rs @@ -122,7 +122,11 @@ fn materialize_unknown_hash_is_not_found() { #[test] fn gc_drops_unpinned_and_keeps_pinned() { - let daemon = support::spawn_daemon(); + // Since iroh-blobs 0.103 gc is a periodic loop inside the store, not + // an on-demand request; run it fast so the sweep happens in-test. + let daemon_dir = tempfile::tempdir().unwrap(); + let daemon = + support::spawn_daemon_with_env(daemon_dir.path(), &[("VARDE_GC_INTERVAL", "1")]); let mut client = support::Client::connect(&daemon.socket); let dir = tempfile::tempdir().unwrap(); @@ -143,11 +147,27 @@ fn gc_drops_unpinned_and_keeps_pinned() { }); assert!(reply.ok, "pin failed: {:?}", reply.error); + // The on-demand request reports the new reality honestly. let reply = client.request(&Request::Gc {}); - assert!(reply.ok, "gc failed: {:?}", reply.error); - match reply.data { - Some(ResponseData::GcDone { blobs_removed }) => assert!(blobs_removed >= 1), - other => panic!("unexpected gc reply: {other:?}"), + assert!(!reply.ok, "on-demand gc should be unimplemented"); + + // Wait for the periodic sweep to collect the loose blob. + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(20); + loop { + let err = materialize( + &mut client, + &doomed, + &dir.path().join("probe"), + MaterializeMode::Copy, + ); + if err.is_err() { + break; + } + assert!( + std::time::Instant::now() < deadline, + "unpinned blob survived gc for 20s" + ); + std::thread::sleep(std::time::Duration::from_millis(500)); } // Pinned tree still materializes; loose blob is gone. @@ -167,21 +187,29 @@ fn gc_drops_unpinned_and_keeps_pinned() { .unwrap_err(); assert_eq!(err, ErrorCode::NotFound); - // Unpinning and collecting again drops the tree too. + // Unpinning lets the next sweep drop the tree too. let reply = client.request(&Request::Unpin { hash: kept_root.clone(), }); assert!(reply.ok); - let reply = client.request(&Request::Gc {}); - assert!(reply.ok); - let err = materialize( - &mut client, - &kept_root, - &dir.path().join("out3"), - MaterializeMode::Copy, - ) - .unwrap_err(); - assert_eq!(err, ErrorCode::NotFound); + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(20); + loop { + let err = materialize( + &mut client, + &kept_root, + &dir.path().join("out3"), + MaterializeMode::Copy, + ); + if let Err(code) = err { + assert_eq!(code, ErrorCode::NotFound); + break; + } + assert!( + std::time::Instant::now() < deadline, + "unpinned tree survived gc for 20s" + ); + std::thread::sleep(std::time::Duration::from_millis(500)); + } } #[test]