diff --git a/TODO.md b/TODO.md index 9606aaf..c2d3e95 100644 --- a/TODO.md +++ b/TODO.md @@ -2,9 +2,38 @@ ## Planned for a future iteration -Larger pieces from external user testing. Both are additive — nothing in the +Larger pieces from external user testing. All are additive — nothing in the current build depends on them. +- [ ] **ZcashNames (ZNS) integration** — human-readable names for FROST + groups/wallets (e.g. `treasury.zcash` → the group's shielded receive + address). Repo: https://github.com/zcashme/zcashnames + + How ZNS works: names are claimed/updated **on-chain via ZIP-321 payment + URIs + signed memos**, and a separate **ZNS Indexer / Directory** service + (SQL-backed, with a web app) indexes them for resolution — so a wallet + resolves a name by querying that directory, not by scanning the chain + itself. Two directions, very different effort: + + - **Resolve (read) — low effort, high value.** Accept a `name.zcash` in the + Send recipient field and in contact entries; resolve it to an address via + the ZNS directory before building the tx. Pairs naturally with the + avatars/account-profile identity work. Gated on the directory exposing a + public resolver API (likely HTTP; no confirmed Rust crate yet — verify). + **Trust caveat:** the resolver is external infrastructure, so ALWAYS show + the resolved shielded address for confirmation before a send — a wrong or + compromised resolver could otherwise redirect funds. Never send to a name + without surfacing what it resolved to. + + - **Register/claim (write) — higher effort.** Let a group publish a name for + its receive address. This is a threshold-authorised on-chain action, so it + fits Cyze's existing FROST send + memo path — but confirm the exact + claim/update memo + ZIP-321 format against the ZNS spec first, and decide + who in the group is allowed to initiate a (re)claim. + + Do the resolver first; it's the piece that makes long unified addresses + usable and is independent of the write path. + - [ ] **User avatars** — let a user pick an avatar, shown next to their name everywhere they are referenced (contacts, group participant lists, the signer picker, "Signed by" in transaction history, the inbox coordinator @@ -29,6 +58,17 @@ current build depends on them. - [ ] **Tailscale `serve` as a fourth hosting option** — alongside Direct URL, Cloudflare Tunnel, and NGINX in Session Configuration. + **Feasibility/impact (2026-08-01):** effort Med, impact Med–High, not gated + by the testnet-send validation. Slots in as a fourth `coordinator_exposure` + variant reusing the existing exposure plumbing + a status probe; no crypto + change (frostd's Noise layer still authenticates end-to-end). Structural + difference from cloudflared: **detect-and-drive a system `tailscale` CLI, + do NOT bundle** — it needs the `tailscaled` daemon (privileged) and a + logged-in tailnet, so the sidecar-spawn pattern doesn't apply. Read the + stable MagicDNS hostname back via `tailscale status --json` as the saved + server URL. Verdict: **do** — best fix for the disposable-quick-tunnel URL + pain (stable, savable, auto-TLS, tailnet-scoped). + Why it is attractive: `tailscale serve https / http://127.0.0.1:` exposes the loopback frostd over the tailnet with a **stable** MagicDNS hostname and an automatically-provisioned, publicly-valid TLS certificate. diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1a9ea0e..0ddd137 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -75,9 +75,9 @@ checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ "alloc-no-stdlib", ] @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "argon2" @@ -167,19 +167,19 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -336,9 +336,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitcoin_hashes" -version = "0.14.100" +version = "0.14.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" +checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "hex-conservative", ] @@ -351,18 +351,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" dependencies = [ "serde_core", ] [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -447,14 +447,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09dc0086e469182132244e9b8d313a0742e1132da43a08c24b9dd3c18e0faf3a" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "brotli" -version = "8.0.3" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -463,9 +463,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -489,9 +489,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" [[package]] name = "byteorder" @@ -501,9 +501,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ "serde", ] @@ -514,7 +514,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cairo-sys-rs", "glib", "libc", @@ -535,9 +535,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.2" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" dependencies = [ "serde_core", ] @@ -562,7 +562,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -586,9 +586,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.63" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "shlex", @@ -629,9 +629,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" @@ -646,9 +646,9 @@ dependencies = [ [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures 0.3.0", @@ -693,9 +693,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.1" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "301b56658598e48f3648647ac6fc887be7e7108eddfa4e9b63fcf3ec58c0cadf" dependencies = [ "clap_builder", "clap_derive", @@ -703,9 +703,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "94a65403d1a1bd28f7dc68eb8506e8874808ee5eecb59298de588e2e1407a078" dependencies = [ "anstream", "anstyle", @@ -715,14 +715,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -737,7 +737,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -806,7 +806,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation", "core-graphics-types", "foreign-types", @@ -819,7 +819,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation", "libc", ] @@ -865,18 +865,18 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -884,18 +884,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crunchy" @@ -943,7 +943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -996,7 +996,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1010,9 +1010,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -1020,27 +1020,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1051,9 +1050,9 @@ checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "dbus" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" dependencies = [ "libc", "libdbus-sys", @@ -1078,12 +1077,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -1094,7 +1092,7 @@ checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1105,7 +1103,7 @@ checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1126,7 +1124,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1199,7 +1197,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "libc", "objc2", @@ -1207,13 +1205,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -1236,7 +1234,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1340,20 +1338,20 @@ dependencies = [ [[package]] name = "either" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "embed-resource" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd" dependencies = [ "cc", "memchr", "rustc_version", - "toml 1.1.2+spec-1.1.0", + "toml 1.1.4+spec-1.1.0", "vswhom", "winreg", ] @@ -1388,7 +1386,8 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306286e8dcc39ab3dfceb74c792ce8baffdab90591321d3ffaae64829734c37f" dependencies = [ "blake2b_simd", "corez", @@ -1434,7 +1433,8 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d42773cb15447644d170be20231a3268600e0c4cea8987d013b93ac973d3cf7" dependencies = [ "blake2b_simd", ] @@ -1453,9 +1453,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "fdeflate" @@ -1557,13 +1557,13 @@ dependencies = [ [[package]] name = "foreign-types-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -1607,7 +1607,7 @@ dependencies = [ "frost-rerandomized 2.2.0", "hex", "postcard", - "rand 0.8.6", + "rand 0.8.7", "reddsa 0.5.1", "serde", "serde_json", @@ -1615,7 +1615,7 @@ dependencies = [ "tauri-build", "tauri-plugin-shell", "tempfile", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "tokio-util", "tracing", @@ -1645,7 +1645,7 @@ dependencies = [ "pczt", "postcard", "prost", - "rand 0.8.6", + "rand 0.8.7", "rcgen", "reddsa 0.5.1", "reqwest 0.12.28", @@ -1654,7 +1654,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "tempfile", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "tokio-util", "toml 0.8.23", @@ -1688,7 +1688,7 @@ dependencies = [ "itertools", "message-io", "postcard", - "rand 0.8.6", + "rand 0.8.7", "reddsa 0.5.1", "reqwest 0.12.28", "rpassword", @@ -1698,7 +1698,7 @@ dependencies = [ "snow", "stable-eyre", "tempfile", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "toml 0.8.23", "uuid", @@ -1723,7 +1723,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect 0.2.0", - "thiserror 2.0.18", + "thiserror 2.0.19", "visibility", "zeroize", ] @@ -1744,7 +1744,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect 0.2.0", - "thiserror 2.0.18", + "thiserror 2.0.19", "visibility", "zeroize", "zeroize_derive", @@ -1798,24 +1798,24 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-executor" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" dependencies = [ "futures-core", "futures-task", @@ -1824,38 +1824,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-core", "futures-io", @@ -1996,25 +1996,23 @@ 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]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", - "wasip2", - "wasip3", + "wasm-bindgen", ] [[package]] @@ -2025,7 +2023,7 @@ checksum = "6cf442baaabe4213ce7d1239afc26c039180b6456da2cededa316ae2c8a77a77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2082,7 +2080,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "futures-channel", "futures-core", "futures-executor", @@ -2110,7 +2108,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2125,9 +2123,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "gobject-sys" @@ -2201,7 +2199,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2237,7 +2235,7 @@ dependencies = [ "halo2_proofs", "lazy_static", "pasta_curves", - "rand 0.8.6", + "rand 0.8.7", "sinsemilla", "subtle", "uint", @@ -2263,9 +2261,9 @@ dependencies = [ [[package]] name = "halo2_proofs" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05713f117155643ce10975e0bee44a274bcda2f4bb5ef29a999ad67c1fa8d4d3" +checksum = "5f63a999d9223fa9d3b9db3031fedc316e6039a0ae0f67394408b16ef670c69f" dependencies = [ "blake2b_simd", "ff", @@ -2385,9 +2383,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -2395,9 +2393,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -2405,9 +2403,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -2439,9 +2437,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" dependencies = [ "atomic-waker", "bytes", @@ -2505,7 +2503,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.4", + "socket2 0.6.5", "tokio", "tower-service", "tracing", @@ -2627,12 +2625,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -2663,7 +2655,8 @@ dependencies = [ [[package]] name = "incrementalmerkletree" version = "0.8.2" -source = "git+https://github.com/zcash/incrementalmerkletree?rev=decefc469dbf1e686b20b7e7dcaa7cb4f122125b#decefc469dbf1e686b20b7e7dcaa7cb4f122125b" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30821f91f0fa8660edca547918dc59812893b497d07c1144f326f07fdd94aba9" dependencies = [ "either", ] @@ -2831,14 +2824,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "js-sys" -version = "0.3.100" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", @@ -2887,7 +2880,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "serde", "unicode-segmentation", ] @@ -2901,12 +2894,6 @@ dependencies = [ "spin", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libappindicator" version = "0.9.0" @@ -2933,9 +2920,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libdbus-sys" @@ -2964,9 +2951,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -3012,9 +2999,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru-slab" @@ -3045,9 +3032,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memoffset" @@ -3139,9 +3126,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "wasi", @@ -3150,9 +3137,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" dependencies = [ "crossbeam-channel", "dpi", @@ -3165,7 +3152,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "windows-sys 0.61.2", ] @@ -3190,7 +3177,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "jni-sys 0.3.1", "log", "ndk-sys", @@ -3244,9 +3231,9 @@ checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d" [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", @@ -3254,9 +3241,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" @@ -3306,7 +3293,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -3325,7 +3312,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-core-foundation", @@ -3338,7 +3325,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-foundation", ] @@ -3359,7 +3346,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "dispatch2", "objc2", ] @@ -3370,7 +3357,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "dispatch2", "objc2", "objc2-core-foundation", @@ -3403,7 +3390,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -3430,7 +3417,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-core-foundation", @@ -3442,7 +3429,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", ] @@ -3453,7 +3440,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -3465,7 +3452,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-cloud-kit", @@ -3496,7 +3483,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-app-kit", @@ -3533,14 +3520,13 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.5" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" +checksum = "a0b3d059e795d52b8a72fef45658620edd4d9c359b338564aa14391ffa511ed5" dependencies = [ "dunce", "is-wsl", "libc", - "pathdiff", ] [[package]] @@ -3560,9 +3546,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -3579,9 +3565,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" -version = "0.15.0-pre.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77752de9c2865ca4a0d962b201b473d60bbe438d53a964a8707ec4bd401d631" +checksum = "793e2e8c2323f35f082d1b3467ca8f576d646f9c93aef8c5168809d099245af8" dependencies = [ "aes", "bitvec", @@ -3600,7 +3586,7 @@ dependencies = [ "memuse", "nonempty", "pasta_curves", - "rand 0.8.6", + "rand 0.8.7", "rand_core 0.6.4", "reddsa 0.5.2", "serde", @@ -3693,29 +3679,24 @@ dependencies = [ [[package]] name = "pasta_curves" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +checksum = "3437083215c505e867eea5478371feba43d7689d6d15ec0a209eb46fb0d4cda6" dependencies = [ "blake2b_simd", "ff", "group", "lazy_static", - "rand 0.8.6", + "rand 0.8.7", "static_assertions", "subtle", ] -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - [[package]] name = "pczt" -version = "0.7.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d4693dcb3d72f30064e0fdab122292d803bd9325a95b25df08679cf895452f" dependencies = [ "blake2b_simd", "bls12_381", @@ -3818,7 +3799,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -3847,7 +3828,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -3874,9 +3855,9 @@ checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ "base64 0.22.1", "indexmap 2.14.0", @@ -3904,7 +3885,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "crc32fast", "fdeflate", "flate2", @@ -3984,7 +3965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -4012,7 +3993,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.12+spec-1.1.0", + "toml_edit 0.25.13+spec-1.1.0", ] [[package]] @@ -4041,9 +4022,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] @@ -4073,7 +4054,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.117", + "syn 2.0.119", "tempfile", ] @@ -4087,7 +4068,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -4101,18 +4082,18 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -4121,8 +4102,8 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.4", - "thiserror 2.0.18", + "socket2 0.6.5", + "thiserror 2.0.19", "tokio", "tracing", "web-time", @@ -4130,20 +4111,21 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", - "rand 0.9.4", + "rand 0.10.2", + "rand_pcg", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.18", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -4151,23 +4133,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.4", + "socket2 0.6.5", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -4192,33 +4174,23 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" dependencies = [ "libc", - "rand_chacha 0.3.1", + "rand_chacha", "rand_core 0.6.4", ] [[package]] name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", -] - -[[package]] -name = "rand" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "chacha20 0.10.0", - "getrandom 0.4.2", + "chacha20 0.10.1", + "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -4232,16 +4204,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - [[package]] name = "rand_core" version = "0.6.4" @@ -4251,15 +4213,6 @@ dependencies = [ "getrandom 0.2.17", ] -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - [[package]] name = "rand_core" version = "0.10.1" @@ -4273,7 +4226,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.6", + "rand 0.8.7", +] + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", ] [[package]] @@ -4348,7 +4310,7 @@ dependencies = [ "pasta_curves", "rand_core 0.6.4", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "zeroize", ] @@ -4370,7 +4332,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", ] [[package]] @@ -4392,34 +4354,34 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "ref-cast" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] name = "regex" -version = "1.12.4" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -4429,9 +4391,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", @@ -4575,7 +4537,7 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -4587,15 +4549,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -4612,7 +4574,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -4621,9 +4583,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" dependencies = [ "log", "once_cell", @@ -4648,9 +4610,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "web-time", "zeroize", @@ -4669,9 +4631,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" @@ -4711,7 +4673,7 @@ dependencies = [ "jubjub", "lazy_static", "memuse", - "rand 0.8.6", + "rand 0.8.7", "rand_core 0.6.4", "redjubjub", "subtle", @@ -4759,9 +4721,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" dependencies = [ "dyn-clone", "ref-cast", @@ -4778,7 +4740,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -4844,7 +4806,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation", "core-foundation-sys", "libc", @@ -4867,7 +4829,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cssparser", "derive_more 2.1.1", "log", @@ -4892,9 +4854,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -4914,22 +4876,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -4940,14 +4902,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -4958,13 +4920,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -4999,17 +4961,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.17.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.14.0", "schemars 0.9.0", - "schemars 1.2.1", + "schemars 1.2.2", "serde_core", "serde_json", "serde_with_macros", @@ -5018,14 +4981,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.17.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -5067,7 +5030,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -5081,9 +5044,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" dependencies = [ "cfg-if", "cpufeatures 0.2.17", @@ -5114,10 +5077,11 @@ dependencies = [ [[package]] name = "shardtree" -version = "0.6.2" -source = "git+https://github.com/zcash/incrementalmerkletree?rev=decefc469dbf1e686b20b7e7dcaa7cb4f122125b#decefc469dbf1e686b20b7e7dcaa7cb4f122125b" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8147447aed7be4736e271825b8c3a4432efb7182e71363169b572371ddef452e" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "either", "incrementalmerkletree", "tracing", @@ -5182,9 +5146,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "sinsemilla" @@ -5243,9 +5207,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", @@ -5301,9 +5265,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" dependencies = [ "lock_api", ] @@ -5423,9 +5387,20 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "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", @@ -5449,7 +5424,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -5471,7 +5446,7 @@ version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "core-foundation", "core-graphics", @@ -5507,13 +5482,13 @@ dependencies = [ [[package]] name = "tao-macros" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +checksum = "5f7eeb6d99155545da6150a1795945f16ac9c178deb2a5f2e74d776107bd5849" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -5530,9 +5505,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.11.2" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" +checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" dependencies = [ "anyhow", "bytes", @@ -5569,7 +5544,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", "tray-icon", "url", @@ -5581,9 +5556,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" dependencies = [ "anyhow", "cargo_toml", @@ -5602,9 +5577,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" dependencies = [ "base64 0.22.1", "brotli", @@ -5618,9 +5593,9 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "syn 2.0.117", + "syn 2.0.119", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "url", "uuid", @@ -5629,23 +5604,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e126abc9e84e35cdfd01596140a73a1850cdb0df0a23acf0185776c30b469a6e" +checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020" dependencies = [ "anyhow", "glob", @@ -5674,15 +5649,15 @@ dependencies = [ "shared_child", "tauri", "tauri-plugin", - "thiserror 2.0.18", + "thiserror 2.0.19", "tokio", ] [[package]] name = "tauri-runtime" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" dependencies = [ "cookie", "dpi", @@ -5696,7 +5671,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.19", "url", "webkit2gtk", "webview2-com", @@ -5705,9 +5680,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.11.2" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", "http", @@ -5731,9 +5706,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" dependencies = [ "anyhow", "brotli", @@ -5759,8 +5734,8 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.18", - "toml 1.1.2+spec-1.1.0", + "thiserror 2.0.19", + "toml 1.1.4+spec-1.1.0", "url", "urlpattern", "uuid", @@ -5775,7 +5750,7 @@ checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" dependencies = [ "dunce", "embed-resource", - "toml 1.1.2+spec-1.1.0", + "toml 1.1.4+spec-1.1.0", ] [[package]] @@ -5785,7 +5760,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -5793,12 +5768,11 @@ dependencies = [ [[package]] name = "tendril" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" dependencies = [ "new_debug_unreachable", - "utf-8", ] [[package]] @@ -5812,11 +5786,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.19", ] [[package]] @@ -5827,46 +5801,45 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] name = "time" -version = "0.3.37" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -5884,9 +5857,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -5899,30 +5872,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes", "libc", - "mio 1.2.1", + "mio 1.2.2", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.4", + "socket2 0.6.5", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -5937,9 +5910,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite", @@ -5948,13 +5921,14 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] @@ -5988,9 +5962,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.2+spec-1.1.0" +version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap 2.14.0", "serde_core", @@ -5998,7 +5972,7 @@ dependencies = [ "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -6066,23 +6040,23 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.12+spec-1.1.0" +version = "0.25.13+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -6093,9 +6067,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tonic" @@ -6115,7 +6089,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2 0.6.4", + "socket2 0.6.5", "sync_wrapper", "tokio", "tokio-rustls", @@ -6136,7 +6110,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -6161,7 +6135,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.117", + "syn 2.0.119", "tempfile", "tonic-build", ] @@ -6191,7 +6165,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "bytes", "futures-util", "http", @@ -6234,7 +6208,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -6248,9 +6222,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.23.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" +checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" dependencies = [ "crossbeam-channel", "dirs 6.0.0", @@ -6264,7 +6238,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "windows-sys 0.61.2", ] @@ -6286,7 +6260,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.8.6", + "rand 0.8.7", "sha1", "thiserror 1.0.69", "url", @@ -6379,12 +6353,6 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "universal-hash" version = "0.5.1" @@ -6446,13 +6414,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.3" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", - "rand 0.10.1", + "rand 0.10.2", "serde_core", "wasm-bindgen", ] @@ -6483,7 +6451,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -6533,27 +6501,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -6564,9 +6523,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.73" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54568702fabf5d4849ce2b90fadfa64168a097eaf4b351ce9df8b687a0086aaf" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -6574,9 +6533,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6584,48 +6543,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.5.0" @@ -6639,23 +6576,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.13.0", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.100" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0871acf327f283dc6da28a1696cdc64fb355ba9f935d052021fa77f35cce69" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -6673,9 +6598,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" dependencies = [ "phf", "phf_codegen", @@ -6729,9 +6654,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" dependencies = [ "rustls-pki-types", ] @@ -6758,7 +6683,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -6767,16 +6692,16 @@ version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", "windows", "windows-core 0.61.2", ] [[package]] name = "which" -version = "8.0.4" +version = "8.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d7cd18d4acb58fb3cdfe9ea54e6cd96a4e7d4cc45c56338b236e82dad47248" +checksum = "8f3ef584124b911bcc3875c2f1472e80f24361ceb789bd1c62b3e9a3df9ff43c" dependencies = [ "libc", ] @@ -6894,7 +6819,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -6905,7 +6830,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -7301,9 +7226,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] @@ -7318,100 +7243,12 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck 0.5.0", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck 0.5.0", - "indexmap 2.14.0", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.13.0", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -7451,7 +7288,7 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.18", + "thiserror 2.0.19", "url", "webkit2gtk", "webkit2gtk-sys", @@ -7514,7 +7351,7 @@ dependencies = [ "derive_more 0.99.20", "ed25519", "ed25519-dalek", - "rand 0.8.6", + "rand 0.8.7", "sha2 0.10.9", "x25519-dalek", "zeroize", @@ -7548,14 +7385,15 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", "synstructure", ] [[package]] name = "zcash_address" -version = "0.13.0-pre.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a854b28c07dba372f4410ea8ad62b4bf7d5c2bf8be32fc4b31bc0db6521a975" dependencies = [ "bech32", "bs58", @@ -7567,8 +7405,9 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.23.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.24.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832ace878c125814bb9e82228d3661499124c6f2936e60fc1df3c6876eb54624" dependencies = [ "async-trait", "base64 0.22.1", @@ -7602,7 +7441,6 @@ dependencies = [ "shardtree", "subtle", "time", - "time-core", "tonic", "tonic-prost", "tonic-prost-build", @@ -7622,11 +7460,12 @@ dependencies = [ [[package]] name = "zcash_client_sqlite" -version = "0.21.1" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.22.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a789c0038359968f93bfe3952d2b942e3bae5582f79c2f31137c6fd736a225" dependencies = [ "bip32", - "bitflags 2.13.0", + "bitflags 2.13.1", "bs58", "byteorder", "document-features", @@ -7638,7 +7477,7 @@ dependencies = [ "nonempty", "orchard", "prost", - "rand 0.8.6", + "rand 0.8.7", "rand_core 0.6.4", "rand_distr", "regex", @@ -7659,6 +7498,7 @@ dependencies = [ "zcash_client_backend", "zcash_encoding", "zcash_keys", + "zcash_pool_migration", "zcash_primitives", "zcash_protocol", "zcash_script", @@ -7669,7 +7509,8 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1440921903cdb86133fb9e2fe800be488015db2939a30bedb413078a1acb0306" dependencies = [ "corez", "hex", @@ -7678,8 +7519,9 @@ dependencies = [ [[package]] name = "zcash_keys" -version = "0.15.0-pre.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def800f128e459eedebc900f36f408eaf0687634128dcf64ecfeaeebc3e16c14" dependencies = [ "bech32", "bip32", @@ -7707,9 +7549,9 @@ dependencies = [ [[package]] name = "zcash_note_encryption" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77efec759c3798b6e4d829fcc762070d9b229b0f13338c40bf993b7b609c2272" +checksum = "e1cb1b9170c94370e3d66c5cc0877661db743337588b64de7711239eed462198" dependencies = [ "chacha20 0.9.1", "chacha20poly1305", @@ -7718,10 +7560,32 @@ dependencies = [ "subtle", ] +[[package]] +name = "zcash_pool_migration" +version = "0.1.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9010904169a92805128b3a8eab0dd4ff79fd164dd416af68aaeac5c7ebbd2522" +dependencies = [ + "corez", + "getset", + "incrementalmerkletree", + "libm", + "orchard", + "pczt", + "rand_core 0.6.4", + "shardtree", + "zcash_client_backend", + "zcash_keys", + "zcash_primitives", + "zcash_protocol", + "zip32", +] + [[package]] name = "zcash_primitives" -version = "0.29.0-pre.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ca4de11896f704ffe6319c2cd7bc8fc6ab31a55cec80d26def15c009d83678" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -7750,8 +7614,9 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.10.0-pre.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f074493fff337207e28bcfa5bbdf0e2a125c4203a4bdd07e72067eea81e9e7b" dependencies = [ "corez", "document-features", @@ -7767,14 +7632,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f872800287d118be71bdf6fe8c869c6a6ff6fb0a5762f68fb2af54c97edf0f2" dependencies = [ "bip32", - "bitflags 2.13.0", + "bitflags 2.13.1", "bounded-vec", "hex", "ripemd 0.1.3", "secp256k1", "sha1", "sha2 0.10.9", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -7788,8 +7653,9 @@ dependencies = [ [[package]] name = "zcash_transparent" -version = "0.9.0-pre.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "547c012778bae17f58007731af074d638aa146ab0ecfc120adebf23d049aff6c" dependencies = [ "bip32", "bs58", @@ -7812,22 +7678,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.52" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.52" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -7847,15 +7713,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "serde", "zeroize_derive", @@ -7863,13 +7729,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -7902,7 +7768,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -7920,8 +7786,9 @@ dependencies = [ [[package]] name = "zip321" -version = "0.8.0" -source = "git+https://github.com/zecrocks/librustzcash?branch=ironwood-scan-model#71da9dddc194f8adf003b14c7957d03a4836c3cd" +version = "0.9.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb464491970d9b61889e4f2b7b00fb9f471a33692e5c0de3122fdc575d8067ab" dependencies = [ "base64 0.22.1", "nom", @@ -7932,6 +7799,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c2095e9..ec56688 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -68,11 +68,3 @@ dirs = "5" tracing = "0.1" sha2 = "0.10" base64 = "0.22" - -# IRONWOOD/NU6.3 TESTNET SPIKE: the zecrocks librustzcash `ironwood-scan-model` -# fork depends on explicit checkpoint-retention shardtree/incrementalmerkletree -# (zcash/incrementalmerkletree main, not yet published), so a downstream consumer -# must replicate the fork's patch. Remove once a published shardtree release cut. -[patch.crates-io] -shardtree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "decefc469dbf1e686b20b7e7dcaa7cb4f122125b" } -incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "decefc469dbf1e686b20b7e7dcaa7cb4f122125b" } diff --git a/src-tauri/core/Cargo.toml b/src-tauri/core/Cargo.toml index b8c2d8e..108f655 100644 --- a/src-tauri/core/Cargo.toml +++ b/src-tauri/core/Cargo.toml @@ -35,24 +35,24 @@ base64 = { workspace = true } # which breaks against xeddsa 1.1 (rand_core trait changes). xeddsa = "=1.0.2" -# Optional Zcash key/address derivation (spike). Behind a feature so the heavy +# Optional Zcash key/address derivation. Behind a feature so the heavy # orchard/halo2 dependency tree stays out of the default build. # -# IRONWOOD/NU6.3 TESTNET SPIKE: the zcash_* cohort is pinned to zecrocks' -# librustzcash fork branch `ironwood-scan-model`, which carries the real testnet -# NU6.3 branch id (0x37a5165b) plus the Ironwood send path + turnstile -# enforcement. orchard moves to 0.15.0-pre.2 (still ships `unstable-frost`). -# These are PRE-RELEASE deps appropriate for a testnet build only. See -# src-tauri/Cargo.toml for the required [patch.crates-io] incrementalmerkletree -# pin the fork depends on. -orchard = { version = "0.15.0-pre.2", optional = true, features = ["unstable-frost"] } -zcash_address = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true } +# IRONWOOD/NU6.3: the zcash_* cohort tracks the PUBLISHED crates.io release wave +# (no git fork, no [patch.crates-io]). These carry the real NU6.3 branch id +# (0x37a5165b) and, crucially, Ironwood/V6 PCZT construction +# (zcash_client_backend 0.24 builds a version-6 tx with an Ironwood bundle from +# NU6.3 onward). orchard stays on the `unstable-frost` feature Cyze's threshold +# signing needs. zcash_client_backend/sqlite are release candidates; the rest +# are stable. +orchard = { version = "0.15.4", optional = true, features = ["unstable-frost"] } +zcash_address = { version = "0.13", optional = true } pasta_curves = { version = "0.5", optional = true } ff = { version = "0.13", optional = true } -# Wallet/light-client stack (feature `wallet`, spike 5.0). Heavy: pulls the -# zcash light-client backend, lightwalletd gRPC, PCZT builder, and sqlite. -zcash_client_backend = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true, default-features = false, features = [ +# Wallet/light-client stack (feature `wallet`). Heavy: pulls the zcash +# light-client backend, lightwalletd gRPC, PCZT builder, and sqlite. +zcash_client_backend = { version = "=0.24.0-rc.6", optional = true, default-features = false, features = [ "orchard", "sync", "lightwalletd-tonic", @@ -60,10 +60,10 @@ zcash_client_backend = { git = "https://github.com/zecrocks/librustzcash", branc "lightwalletd-tonic-tls-webpki-roots", "pczt", ] } -zcash_client_sqlite = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true, features = ["orchard", "transparent-inputs", "unstable", "serde"] } -pczt = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true, features = ["signer"] } -zcash_keys = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true, features = ["orchard"] } -zcash_protocol = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true } +zcash_client_sqlite = { version = "=0.22.0-rc.6", optional = true, features = ["orchard", "transparent-inputs", "unstable", "serde"] } +pczt = { version = "0.9.1", optional = true, features = ["signer"] } +zcash_keys = { version = "0.16.1", optional = true, features = ["orchard"] } +zcash_protocol = { version = "0.10.3", optional = true } tonic = { version = "0.14", optional = true, default-features = false, features = ["transport", "tls-webpki-roots"] } # SQLCipher (bundled amalgamation) so the per-group wallet database is encrypted # at rest. Feature-unifies with zcash_client_sqlite's `bundled` rusqlite: the @@ -73,7 +73,7 @@ tonic = { version = "0.14", optional = true, default-features = false, features rusqlite = { version = "0.37", optional = true, features = ["bundled-sqlcipher-vendored-openssl"] } prost = { version = "0.14", optional = true } async-trait = { version = "0.1", optional = true } -zcash_primitives = { git = "https://github.com/zecrocks/librustzcash", branch = "ironwood-scan-model", optional = true } +zcash_primitives = { version = "0.30.0", optional = true } [features] # Orchard FVK / unified-address derivation from group key material. diff --git a/src-tauri/core/src/wallet.rs b/src-tauri/core/src/wallet.rs index 3716320..0b83472 100644 --- a/src-tauri/core/src/wallet.rs +++ b/src-tauri/core/src/wallet.rs @@ -106,21 +106,22 @@ pub fn branch_id_for_height(network: WalletNetwork, height: u64) -> String { /// The NU6.3 / Ironwood consensus branch id (little-endian u32, printed as /// 8-digit hex). Orchard actions mined under this upgrade prove against the /// `PostNu6_3` circuit (the fixed circuit plus the `disableCrossAddress` -/// constraint). Testnet activated it at 4,134,000; mainnet has not (yet). +/// constraint). Activated on testnet at 4,134,000 and on mainnet at 3,428,143 +/// (see `zcash_protocol` activation tables), so both live networks are past it. const NU6_3_BRANCH_ID: &str = "37a5165b"; /// The Orchard proving/verifying circuit version to use for a transaction mined /// at `height` on `network`. This MUST match the consensus branch active at that /// height, or the proof is rejected by the network: /// -/// - Post-NU6.3 (Ironwood, currently testnet only) → `PostNu6_3`. -/// - Post-NU6.2 (mainnet's current activation) → `FixedPostNu6_2`. +/// - Post-NU6.3 (Ironwood; both testnet and mainnet are past it) → `PostNu6_3`. +/// - Post-NU6.2 but pre-NU6.3 → `FixedPostNu6_2`. /// /// Deriving it from the live branch id — rather than hardcoding one network's /// value — is what lets the same build produce valid transactions on both -/// networks, and automatically switches mainnet over once it activates NU6.3. -/// Both live networks are past NU6.2, so `FixedPostNu6_2` is the correct floor; -/// the historical `InsecurePreNu6_2` circuit is never used for new sends. +/// networks, each picking the circuit for the upgrade active at that height. +/// `FixedPostNu6_2` is the pre-Ironwood floor; the historical `InsecurePreNu6_2` +/// circuit is never used for new sends. #[cfg(feature = "wallet")] fn orchard_circuit_version_for_height( network: WalletNetwork, @@ -561,13 +562,18 @@ pub struct WalletStatus { pub initialized: bool, /// Receiving unified address (from the UFVK), for the configured network. pub address: Option, - /// Aggregate totals (kept for back-compat; equal to the Orchard pool since - /// the group's UFVK is Orchard-only). + /// Aggregate totals across *all* pools the account holds. Post-Ironwood a + /// group's funds are split between the sealed `orchard` pool and the new + /// `ironwood` pool (a turnstile send moves value from the former to the + /// latter), so this is the sum of both — not the Orchard pool alone. pub total_zatoshis: u64, pub spendable_zatoshis: u64, - /// Per-pool breakdown. With an Orchard-only group UFVK, `sapling` and - /// `transparent` are zero — the group cannot hold/spend those pools. + /// Per-pool breakdown. `orchard` is the sealed legacy pool (can be spent but + /// never received into again); `ironwood` is the pool all new shielded value + /// lands in post-NU6.3. `sapling` and `transparent` are zero for an + /// Orchard/Ironwood group UFVK. pub orchard: PoolBalance, + pub ironwood: PoolBalance, pub sapling: PoolBalance, pub transparent: PoolBalance, /// Highest fully-scanned block, and the chain tip the wallet knows about. @@ -592,6 +598,7 @@ pub fn group_status( total_zatoshis: 0, spendable_zatoshis: 0, orchard: PoolBalance::default(), + ironwood: PoolBalance::default(), sapling: PoolBalance::default(), transparent: PoolBalance::default(), synced_height: 0, @@ -612,6 +619,7 @@ pub fn group_status( total_zatoshis: 0, spendable_zatoshis: 0, orchard: PoolBalance::default(), + ironwood: PoolBalance::default(), sapling: PoolBalance::default(), transparent: PoolBalance::default(), synced_height: 0, @@ -621,14 +629,16 @@ pub fn group_status( let summary = db .get_wallet_summary(ConfirmationsPolicy::default()) .map_err(|e| CoreError::Crypto(format!("wallet summary: {e}")))?; - let (total, spendable, orchard, sapling, transparent, synced, tip) = match summary { + let (total, spendable, orchard, ironwood, sapling, transparent, synced, tip) = match summary { Some(s) => { let bal = s.account_balances().values().next(); let total = bal.map(|b| u64::from(b.total())).unwrap_or(0); let spendable = bal.map(|b| u64::from(b.spendable_value())).unwrap_or(0); - // Per-pool breakdown. Orchard is the only pool the group can hold; - // sapling/transparent read 0 with an Orchard-only UFVK. + // Per-pool breakdown. Orchard (sealed) and Ironwood (post-NU6.3) are + // the pools the group holds; sapling/transparent read 0 with an + // Orchard/Ironwood-only UFVK. let orchard = bal.map(|b| pool_balance(b.orchard_balance())).unwrap_or_default(); + let ironwood = bal.map(|b| pool_balance(b.ironwood_balance())).unwrap_or_default(); let sapling = bal.map(|b| pool_balance(b.sapling_balance())).unwrap_or_default(); let transparent = bal .map(|b| { @@ -646,6 +656,7 @@ pub fn group_status( total, spendable, orchard, + ironwood, sapling, transparent, u64::from(s.fully_scanned_height()), @@ -658,6 +669,7 @@ pub fn group_status( PoolBalance::default(), PoolBalance::default(), PoolBalance::default(), + PoolBalance::default(), 0, 0, ), @@ -668,6 +680,7 @@ pub fn group_status( total_zatoshis: total, spendable_zatoshis: spendable, orchard, + ironwood, sapling, transparent, synced_height: synced, @@ -688,25 +701,30 @@ fn pool_balance(b: &zcash_client_backend::data_api::Balance) -> PoolBalance { } } -/// First block a new testnet group's wallet scans when no birthday is recorded -/// or supplied. Sits comfortably before the NU6.3/Ironwood activation -/// (4,134,000), so a group funded any time during Ironwood testing is found by -/// a rebuilt wallet without the user having to supply a height. -const DEFAULT_TESTNET_BIRTHDAY: u64 = 3_800_000; +/// A deep-rescan floor for testnet: sits comfortably before the NU6.3/Ironwood +/// activation (4,134,000), so scanning from here finds a group funded any time +/// during Ironwood testing. +/// +/// This is NOT applied automatically. A brand-new group has no prior funds, so +/// it starts at the chain tip and syncs in seconds; scanning ~350k blocks of +/// pre-creation history was the single largest source of slow first syncs. +/// Recovery of a wiped wallet uses the birthday persisted in settings instead +/// (see the command layer). This constant is only for an *explicit* deep rescan +/// — a user who lost both the wallet db and the recorded birthday and wants to +/// re-discover funds — supplied through `birthday_height`, never as a default. +pub const DEFAULT_TESTNET_BIRTHDAY: u64 = 3_800_000; /// The birthday a brand-new wallet starts from when the caller gives no height -/// and none was recorded for the group. +/// and none was recorded for the group: the chain tip, on both networks. /// -/// Mainnet deliberately has no constant: its chain tip is around 3.4M (NU6.2 -/// activated at 3,364,600), so any fixed height chosen for testnet would sit in -/// mainnet's *future* — the treestate would not exist and the wallet would scan -/// nothing. Mainnet therefore starts at the chain tip, which is correct for a -/// newly created group that cannot hold prior funds. -pub fn default_birthday_height(network: WalletNetwork) -> Option { - match network { - WalletNetwork::Test => Some(DEFAULT_TESTNET_BIRTHDAY), - WalletNetwork::Main => None, - } +/// A newly created group cannot hold funds mined before it existed, so there is +/// nothing to find below the tip — scanning earlier is pure cost. Returning +/// `None` lets [`resolve_scan_from`] resolve the start to the current tip. To +/// recover funds that predate a rebuilt wallet, pass an explicit +/// `birthday_height` (the command layer supplies the persisted one); for a +/// from-scratch testnet rescan, pass [`DEFAULT_TESTNET_BIRTHDAY`]. +pub fn default_birthday_height(_network: WalletNetwork) -> Option { + None } /// Pick the first block to scan: the requested birthday held inside @@ -727,9 +745,11 @@ fn resolve_scan_from(requested: Option, nu5: u64, tip: u64) -> u64 { /// scanning starts from. Idempotent: returns 0 if the account already exists. /// Touches the network (fetches the tip and a treestate). /// -/// `birthday_height` is the first block to scan. Pass `Some(h)` to recover a -/// group whose funds arrived at or after `h` — for example after rebuilding a -/// wiped wallet database. Pass `None` to use [`default_birthday_height`]. +/// `birthday_height` is the first block to scan. Pass `None` for a brand-new +/// group: it holds no prior funds, so it starts at the chain tip and syncs in +/// seconds. Pass `Some(h)` to recover a group whose funds arrived at or after +/// `h` — after rebuilding a wiped wallet database (the command layer supplies +/// the persisted birthday), or [`DEFAULT_TESTNET_BIRTHDAY`] for a full rescan. /// /// Blocks before the birthday are never scanned, so a birthday set too late /// makes existing funds invisible. The height is clamped into @@ -771,6 +791,8 @@ pub async fn init_group_account( let nu5 = params .activation_height(NetworkUpgrade::Nu5) .map_or(0, |a| u64::from(u32::from(a))); + // No requested birthday means a brand-new group: start at the tip. Recovery + // passes an explicit height (persisted birthday or a deep-rescan floor). let scan_from = resolve_scan_from( birthday_height.or_else(|| default_birthday_height(network)), nu5, @@ -904,16 +926,38 @@ impl BlockCache for FsCache { } } +/// How many blocks each sync batch downloads and scans at once when the caller +/// gives no override. Larger batches amortize the per-batch gRPC round-trip and +/// database-transaction overhead across more blocks, which is the dominant cost +/// once trial decryption finds nothing (the common case for a wallet catching up +/// over empty history). Compact blocks are small, so a few thousand per batch is +/// comfortable in memory. Tunable per-install via settings; see [`sync_group`]. +pub const DEFAULT_SYNC_BATCH_SIZE: u32 = 5_000; + +/// Clamp bounds for a caller-supplied batch size. Below the floor the round-trip +/// overhead dominates; above the ceiling a batch's worth of compact blocks can +/// spike memory (they are all held in a `Vec` while the batch is scanned). +pub const MIN_SYNC_BATCH_SIZE: u32 = 500; +pub const MAX_SYNC_BATCH_SIZE: u32 = 25_000; + /// Sync the group's wallet: download and trial-decrypt compact blocks from /// lightwalletd into the local db. Long-running; touches the network. +/// +/// `batch_size` is how many blocks to download and scan per batch; `None` uses +/// [`DEFAULT_SYNC_BATCH_SIZE`]. Any value is clamped into +/// `[MIN_SYNC_BATCH_SIZE, MAX_SYNC_BATCH_SIZE]`. pub async fn sync_group( data_dir: &Path, group_id: &str, network: WalletNetwork, lightwalletd_url: &str, db_key: &[u8], + batch_size: Option, cancel: &tokio_util::sync::CancellationToken, ) -> Result<(), CoreError> { + let batch_size = batch_size + .unwrap_or(DEFAULT_SYNC_BATCH_SIZE) + .clamp(MIN_SYNC_BATCH_SIZE, MAX_SYNC_BATCH_SIZE); let (db_path, blocks_dir) = wallet_paths(data_dir, group_id, network); std::fs::create_dir_all(&blocks_dir)?; let mut db = open_db(&db_path, network, db_key)?; @@ -940,16 +984,31 @@ pub async fn sync_group( biased; _ = cancel.cancelled() => Err(CoreError::Cancelled), res = zcash_client_backend::sync::run( - &mut client, ¶ms, &cache, &mut db, 1000, + &mut client, ¶ms, &cache, &mut db, batch_size, ) => res.map_err(|e| CoreError::Connection(format!("sync: {e}"))), } } -/// One Orchard spend that the group must FROST-sign: its action index and the -/// per-spend re-randomization value α (hex of the canonical scalar encoding), -/// which becomes the FROST coordinator's `randomizer` for that signature. +/// Which shielded pool an action belongs to. Post-NU6.3 a single transaction can +/// carry both bundles at once — e.g. a turnstile send spends Orchard notes (an +/// Orchard-bundle action) while delivering the payment through the Ironwood +/// bundle — so every spend must record which bundle holds it. The two bundles +/// use the same `orchard::pczt` types, so signing differs only in which +/// low-level-signer method reaches the bundle. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum SpendPool { + Orchard, + Ironwood, +} + +/// One shielded spend the group must FROST-sign: which pool's bundle holds it, +/// its action index within that bundle, and the per-spend re-randomization value +/// α (hex of the canonical scalar encoding), which becomes the FROST +/// coordinator's `randomizer` for that signature. #[derive(Debug, Clone, Serialize)] pub struct SpendToSign { + pub pool: SpendPool, pub index: usize, pub alpha_hex: String, } @@ -1000,7 +1059,6 @@ pub async fn prepare_send( db_key: &[u8], ) -> Result { use zcash_keys::address::Address; - use zcash_primitives::transaction::TxVersion; use zcash_protocol::value::Zatoshis; use zcash_protocol::ShieldedPool; @@ -1056,17 +1114,13 @@ pub async fn prepare_send( }) }; - // Constrain the proposal to a version-5 transaction so it matches what the - // PCZT builder can actually construct. - // - // `create_pczt_from_proposal` hardcodes TxVersion::V5 and rejects any step - // that touches the Ironwood pool ("PCZT construction cannot yet produce an - // Ironwood bundle"). Left unconstrained (`None`), the proposal is free to - // route the payment or its change through Ironwood — which post-NU6.3 it - // will, since the Orchard pool is sealed — and the PCZT builder then fails - // with the opaque `ProposalNotSupported`. Passing the version here makes the - // proposal itself avoid Ironwood, so an unbuildable plan is rejected during - // proposal (with a specific reason) rather than after input selection. + // Let the backend choose the transaction version from the target height: + // version 6 (carrying an Ironwood bundle) once NU6.3 is active, version 5 + // before it. Passing `None` is what enables Ironwood sends — post-NU6.3 the + // Orchard pool is sealed, so a shielded payment to a unified address is + // delivered through the Ironwood bundle of a V6 transaction. `lock_inputs` + // is None: Cyze builds and signs one transaction at a time, so there is no + // need to reserve inputs across concurrent proposals. let proposal = propose_standard_transfer_to_address::<_, _, std::convert::Infallible>( &mut db, ¶ms, @@ -1078,7 +1132,8 @@ pub async fn prepare_send( memo_bytes, None, // change memo ShieldedPool::Orchard, - Some(TxVersion::V5), + None, // lock_inputs + None, // proposed_version: derive V5/V6 from the target height ) .map_err(|e| CoreError::Ceremony(format!("propose transfer: {e:?}")))?; @@ -1090,23 +1145,12 @@ pub async fn prepare_send( account_id, OvkPolicy::Sender, &proposal, - None, // target_expiry_height: use the proposal's default expiry + None, // expiry_height: use the proposal's default expiry + // Orchard-bundle padding; the Ironwood bundle derives its own from the + // proposal so it matches the action count the fee was computed from. + zcash_primitives::transaction::builder::BundlePadding::DEFAULT, ) - .map_err(|e| match e { - // The PCZT builder only emits version-5 transactions, so it refuses any - // plan that moves value through the Ironwood pool. Cyze signs via PCZT - // (FROST needs it to expose each spend's α and to apply the group's - // signature), so there is no fallback path until the Zcash crates can - // build Ironwood PCZTs. - zcash_client_backend::data_api::error::Error::ProposalNotSupported => CoreError::Ceremony( - "this transaction needs the Ironwood pool, which the Zcash PCZT builder \ - cannot construct yet (it only builds version-5 transactions). Since \ - NU6.3 sealed the Orchard pool, shielded sends and shielded change now \ - require Ironwood. Unshielding to a transparent address may still work." - .to_string(), - ), - other => CoreError::Ceremony(format!("create pczt: {other:?}")), - })?; + .map_err(|e| CoreError::Ceremony(format!("create pczt: {e:?}")))?; // Ironwood cohort: Pczt::serialize now consumes self and returns Result // (postcard EncodingError). Serialize a clone since `pczt` is still needed @@ -1121,9 +1165,9 @@ pub async fn prepare_send( .map_err(|e| CoreError::Ceremony(format!("signer: {e:?}")))? .shielded_sighash(); - // Read each real Orchard spend's α (the re-randomization the FROST signers - // must use). Dummy padding actions have zero value and are skipped. - let spends = orchard_spends_to_sign(pczt)?; + // Read each real spend's α (the re-randomization the FROST signers must + // use), across both the Orchard and Ironwood bundles. + let spends = spends_to_sign(pczt)?; Ok(DraftTransaction { pczt_hex, @@ -1137,47 +1181,147 @@ pub async fn prepare_send( }) } -/// Extract the (index, α) of each real Orchard spend in a PCZT. Requires -/// orchard's `unstable-frost` feature (which exposes `spend().alpha()`). -fn orchard_spends_to_sign(pczt: pczt::Pczt) -> Result, CoreError> { +/// Collect every spend the group must FROST-sign, across both the Orchard and +/// Ironwood bundles, tagged with its pool and α. Requires orchard's +/// `unstable-frost` feature (which exposes `spend().alpha()`). Orchard spends are +/// listed first, then Ironwood; the order only needs to be stable, since each +/// spend carries its own pool + index for application. +/// +/// A spend needs the group's signature iff it still lacks a `spend_auth_sig`: +/// this runs after `create_pczt_from_proposal`, whose IO Finalizer has already +/// signed every dummy padding spend from its `dummy_sk`, so the only spends left +/// unsigned are the wallet's own notes. Each carries an α to sign with. The old +/// heuristic keyed on `value != 0`, which wrongly skipped the **zero-value real +/// spend** the turnstile-out construction adds to the Orchard bundle — leaving it +/// unauthorized and failing extraction with `MissingSpendAuthSig`. +fn spends_to_sign(pczt: pczt::Pczt) -> Result, CoreError> { use ff::PrimeField; - use orchard::value::NoteValue; - use pczt::roles::low_level_signer::OrchardParseError; - - let mut spends = Vec::new(); - let mut parse_err: Option = None; - pczt::roles::low_level_signer::Signer::new(pczt) - .sign_orchard_with(|_pczt, bundle, _| { - for (index, action) in bundle.actions().iter().enumerate() { - let is_real = action.spend().value().is_some_and(|v| v != NoteValue::default()); - if let (true, Some(alpha)) = (is_real, action.spend().alpha()) { - spends.push(SpendToSign { + use pczt::roles::low_level_signer::{OrchardParseError, Signer}; + + // Append every not-yet-signed spend of one already-parsed bundle, tagging + // its pool. `spend_auth_sig().is_none()` selects exactly the spends the group + // must authorize (dummies were already signed by the IO Finalizer); `alpha` + // is the re-randomization those signatures must use. + fn collect(bundle: &orchard::pczt::Bundle, pool: SpendPool, out: &mut Vec) { + for (index, action) in bundle.actions().iter().enumerate() { + let spend = action.spend(); + if spend.spend_auth_sig().is_none() { + if let Some(alpha) = spend.alpha() { + out.push(SpendToSign { + pool, index, alpha_hex: hex::encode(alpha.to_repr()), }); } } + } + } + + let mut spends = Vec::new(); + let signer = Signer::new(pczt) + .sign_orchard_with(|_pczt, bundle, _| { + collect(bundle, SpendPool::Orchard, &mut spends); Ok::<_, OrchardParseError>(()) }) - .map_err(|e: OrchardParseError| { - parse_err = Some(format!("{e:?}")); + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read orchard spends: {e:?}")))?; + signer + .sign_ironwood_with(|_pczt, bundle, _| { + collect(bundle, SpendPool::Ironwood, &mut spends); + Ok::<_, OrchardParseError>(()) }) - .ok(); - if let Some(e) = parse_err { - return Err(CoreError::Ceremony(format!("read orchard spends: {e}"))); - } + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read ironwood spends: {e:?}")))?; Ok(spends) } -/// Apply FROST-produced Orchard spend-auth signatures to a draft PCZT, returning -/// the signed PCZT (hex). `signatures` are (spend index, 64-byte sig hex). -pub fn apply_orchard_signatures( +/// Whether the PCZT carries any actions in each pool's bundle, as +/// `(orchard, ironwood)`. Used to prove only the bundles a transaction actually +/// has — proving an empty bundle fails its anchor check. +fn bundle_presence(pczt: &pczt::Pczt) -> Result<(bool, bool), CoreError> { + use pczt::roles::low_level_signer::{OrchardParseError, Signer}; + + let mut has_orchard = false; + let mut has_ironwood = false; + let signer = Signer::new(pczt.clone()) + .sign_orchard_with(|_pczt, bundle, _| { + has_orchard = !bundle.actions().is_empty(); + Ok::<_, OrchardParseError>(()) + }) + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read orchard bundle: {e:?}")))?; + signer + .sign_ironwood_with(|_pczt, bundle, _| { + has_ironwood = !bundle.actions().is_empty(); + Ok::<_, OrchardParseError>(()) + }) + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read ironwood bundle: {e:?}")))?; + Ok((has_orchard, has_ironwood)) +} + +/// Find every shielded spend that still lacks a spend-authorization signature, +/// across both Orchard-protocol bundles, described precisely. +/// +/// The `TransactionExtractor` requires a `spend_auth_sig` on *every* action and +/// otherwise fails late and opaquely with `MissingSpendAuthSig`. By the time we +/// reach it, dummy padding spends have been signed by the IO Finalizer (it +/// consumes their `dummy_sk`) and real spends have been FROST-signed and applied +/// ([`apply_signatures`]). Anything still unsigned is a bug in *this* signing +/// path — most likely a real spend that [`spends_to_sign`] failed to enumerate, +/// or a dummy the IO Finalizer skipped — and we want to surface it here, before +/// the expensive proving/broadcast, with enough detail to fix it. The returned +/// strings distinguish the two cases (a real spend still carrying `value`/`alpha` +/// vs. a dummy whose `dummy_sk` was never consumed). +fn find_unsigned_spends(pczt: &pczt::Pczt) -> Result, CoreError> { + use orchard::value::NoteValue; + use pczt::roles::low_level_signer::{OrchardParseError, Signer}; + + fn scan(bundle: &orchard::pczt::Bundle, pool: &str, out: &mut Vec) { + for (index, action) in bundle.actions().iter().enumerate() { + let spend = action.spend(); + if spend.spend_auth_sig().is_some() { + continue; // already authorized + } + let is_real = spend.value().is_some_and(|v| v != NoteValue::default()); + let has_alpha = spend.alpha().is_some(); + let has_dummy_sk = spend.dummy_sk().is_some(); + let kind = if is_real { + "REAL spend never FROST-signed (spends_to_sign missed it?)" + } else if has_dummy_sk { + "dummy with unconsumed dummy_sk (IO Finalizer skipped it?)" + } else { + "zero-value spend left unsigned" + }; + out.push(format!( + "{pool} bundle action {index}: {kind} [alpha_present={has_alpha}]" + )); + } + } + + let mut unsigned = Vec::new(); + let signer = Signer::new(pczt.clone()) + .sign_orchard_with(|_pczt, bundle, _| { + scan(bundle, "orchard", &mut unsigned); + Ok::<_, OrchardParseError>(()) + }) + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read orchard bundle: {e:?}")))?; + signer + .sign_ironwood_with(|_pczt, bundle, _| { + scan(bundle, "ironwood", &mut unsigned); + Ok::<_, OrchardParseError>(()) + }) + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("read ironwood bundle: {e:?}")))?; + Ok(unsigned) +} + +/// Apply FROST-produced spend-auth signatures to a draft PCZT, returning the +/// signed PCZT (hex). Each entry is `(pool, action index, 64-byte sig hex)`; the +/// pool selects which bundle the signature is applied to, so a turnstile +/// transaction that spends from both pools is signed correctly. +pub fn apply_signatures( pczt_hex: &str, sighash_hex: &str, - signatures: Vec<(usize, String)>, + signatures: Vec<(SpendPool, usize, String)>, ) -> Result { use orchard::primitives::redpallas::{Signature, SpendAuth}; - use pczt::roles::low_level_signer::OrchardParseError; + use pczt::roles::low_level_signer::{OrchardParseError, Signer}; let pczt = pczt::Pczt::parse( &hex::decode(pczt_hex.trim()).map_err(|e| CoreError::Ceremony(format!("pczt hex: {e}")))?, @@ -1188,34 +1332,71 @@ pub fn apply_orchard_signatures( .and_then(|b| b.try_into().ok()) .ok_or_else(|| CoreError::Ceremony("sighash must be 32 bytes hex".into()))?; - let sigs: Vec<(usize, Signature)> = signatures - .into_iter() - .map(|(idx, sig_hex)| { - let bytes: [u8; 64] = hex::decode(sig_hex.trim()) - .ok() - .and_then(|b| b.try_into().ok()) - .ok_or_else(|| CoreError::Ceremony("signature must be 64 bytes hex".into()))?; - Ok((idx, Signature::::from(bytes))) - }) - .collect::>()?; + // Decode and split the signatures by pool. + let mut orchard_sigs: Vec<(usize, Signature)> = Vec::new(); + let mut ironwood_sigs: Vec<(usize, Signature)> = Vec::new(); + for (pool, idx, sig_hex) in signatures { + let bytes: [u8; 64] = hex::decode(sig_hex.trim()) + .ok() + .and_then(|b| b.try_into().ok()) + .ok_or_else(|| CoreError::Ceremony("signature must be 64 bytes hex".into()))?; + let sig = Signature::::from(bytes); + match pool { + SpendPool::Orchard => orchard_sigs.push((idx, sig)), + SpendPool::Ironwood => ironwood_sigs.push((idx, sig)), + } + } + // Applying a signature to the wrong action index is a hard error rather than + // a bad-signature rejection at broadcast, so surface it precisely. let mut apply_err: Option = None; - let signer = pczt::roles::low_level_signer::Signer::new(pczt) - .sign_orchard_with(|_pczt, bundle, _| { - for (idx, sig) in sigs { - if let Err(e) = bundle.actions_mut()[idx].apply_signature(sighash, sig) { - apply_err = Some(format!("spend {idx}: {e:?}")); - break; - } + let apply = |bundle: &mut orchard::pczt::Bundle, + sigs: &[(usize, Signature)], + pool: &str, + err: &mut Option| { + for (idx, sig) in sigs { + if let Err(e) = bundle.actions_mut()[*idx].apply_signature(sighash, sig.clone()) { + *err = Some(format!("{pool} spend {idx}: {e:?}")); + break; } + } + }; + + let signer = Signer::new(pczt) + .sign_orchard_with(|_pczt, bundle, _| { + apply(bundle, &orchard_sigs, "orchard", &mut apply_err); Ok::<_, OrchardParseError>(()) }) - .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("apply: {e:?}")))?; + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("apply orchard: {e:?}")))?; + let signer = signer + .sign_ironwood_with(|_pczt, bundle, _| { + apply(bundle, &ironwood_sigs, "ironwood", &mut apply_err); + Ok::<_, OrchardParseError>(()) + }) + .map_err(|e: OrchardParseError| CoreError::Ceremony(format!("apply ironwood: {e:?}")))?; if let Some(e) = apply_err { return Err(CoreError::Ceremony(format!("invalid signature for {e}"))); } - // Ironwood cohort: Pczt::serialize now returns Result (postcard EncodingError). - Ok(hex::encode(signer.finish().serialize().map_err(|e| { + let signed = signer.finish(); + + // Completeness guard: every shielded spend must now be authorized, or the + // TransactionExtractor fails late and opaquely with `MissingSpendAuthSig` + // (and only after the expensive proving step). Catch it here instead, naming + // the exact unsigned action(s), so a signing-path gap surfaces early and + // actionably rather than as a doomed broadcast. No transaction is built. + let unsigned = find_unsigned_spends(&signed)?; + if !unsigned.is_empty() { + return Err(CoreError::Ceremony(format!( + "not all spends were authorized, so this transaction would be rejected at \ + broadcast (MissingSpendAuthSig). Unsigned: {}. No transaction was built or \ + sent. This is a bug in the pool-aware signing path — please report it with \ + this message.", + unsigned.join("; ") + ))); + } + + // Pczt::serialize consumes self and returns Result (postcard EncodingError). + Ok(hex::encode(signed.serialize().map_err(|e| { CoreError::Ceremony(format!("serialize pczt: {e:?}")) })?)) } @@ -1225,7 +1406,7 @@ pub fn apply_orchard_signatures( /// key takes several seconds), so it runs on a blocking thread. /// /// This is the final leg of the send pipeline: the group has already applied -/// its threshold signature to every spend ([`apply_orchard_signatures`]); here +/// its threshold signature to every spend ([`apply_signatures`]); here /// we attach the zero-knowledge proof, finalize, extract the transaction (which /// creates the binding signature), and submit it to lightwalletd. pub async fn broadcast_signed( @@ -1239,11 +1420,18 @@ pub async fn broadcast_signed( ) .map_err(|e| CoreError::Ceremony(format!("parse pczt: {e:?}")))?; + // Prove only the bundles this transaction actually carries: a turnstile send + // has both an Orchard bundle (the spends) and an Ironwood bundle (the + // outputs); a pure Ironwood send has only Ironwood; a legacy unshield only + // Orchard. Proving an empty bundle fails its anchor check, so gate on it. + let (has_orchard, has_ironwood) = bundle_presence(&pczt)?; + // Select the Orchard circuit from the consensus branch active at the live // chain tip, so the proof matches what THIS network's validators expect - // (PostNu6_3 on Ironwood testnet, FixedPostNu6_2 on mainnet-NU6.2). A stale - // or hardcoded circuit produces a proof the network rejects. This runs - // seconds before broadcast, so the tip is effectively the tx's mined branch. + // (PostNu6_3 on Ironwood, FixedPostNu6_2 pre-NU6.3). A stale or hardcoded + // circuit produces a proof the network rejects. This runs seconds before + // broadcast, so the tip is effectively the tx's mined branch. Both the + // Orchard and Ironwood pools share this circuit, so one key serves both. let mut client = connect(url).await?; let tip_height = client .get_latest_block(ChainSpec {}) @@ -1261,23 +1449,33 @@ pub async fn broadcast_signed( prover::Prover, spend_finalizer::SpendFinalizer, tx_extractor::TransactionExtractor, }; - // TODO(ironwood-phase3): turnstile sends also populate an *Ironwood* - // output bundle that needs `Prover::create_ironwood_proof` with an - // ironwood_v3 ProvingKey; wire that once the send path targets Ironwood. - - // 1. Orchard zero-knowledge proof. + // `circuit_version` is chosen from the live chain tip above and captured + // by this move closure; one proving/verifying key serves both the + // Orchard and Ironwood bundles, which share that circuit. let pk = ProvingKey::build(circuit_version); - let pczt = Prover::new(pczt) - .create_orchard_proof(&pk) - .map_err(|e| CoreError::Ceremony(format!("orchard proof: {e:?}")))? - .finish(); + + // 1. Zero-knowledge proof for each present bundle. + let mut prover = Prover::new(pczt); + if has_orchard { + prover = prover + .create_orchard_proof(&pk) + .map_err(|e| CoreError::Ceremony(format!("orchard proof: {e:?}")))?; + } + if has_ironwood { + prover = prover + .create_ironwood_proof(&pk) + .map_err(|e| CoreError::Ceremony(format!("ironwood proof: {e:?}")))?; + } + let pczt = prover.finish(); // 2. Finalize spends (spend-auth signatures are already applied). let pczt = SpendFinalizer::new(pczt) .finalize_spends() .map_err(|e| CoreError::Ceremony(format!("finalize spends: {e:?}")))?; - // 3. Extract the final transaction (creates the binding signature). + // 3. Extract the final transaction (creates the binding signature). The + // extractor verifies both the Orchard and Ironwood bundles with this one + // vk, since they share the PostNu6_3 circuit. let vk = VerifyingKey::build(circuit_version); let tx = TransactionExtractor::new(pczt) .with_orchard(&vk) @@ -1337,11 +1535,17 @@ pub struct TxRecord { /// clean transaction-list API on `WalletRead`. The tables queried are stable /// parts of `zcash_client_sqlite`'s schema: `transactions`, `accounts`, /// `orchard_received_notes`, and `sent_notes`. -/// Total number of Orchard notes this group has ever received. Used as a coarse -/// "wallet activity" signal to decide when to rotate the receive address (#3): -/// once the count grows, the currently-shown address may have been paid, so the -/// next view hands out a fresh diversifier. Returns 0 when no wallet db exists. -pub fn count_orchard_received_notes( +/// Total number of shielded notes this group has ever received, across both the +/// Orchard and Ironwood pools. Used as a coarse "wallet activity" signal to +/// decide when to rotate the receive address (#3): once the count grows, the +/// currently-shown address may have been paid, so the next view hands out a +/// fresh diversifier. Returns 0 when no wallet db exists. +/// +/// Counting Ironwood too matters post-NU6.3: a payment to the group's unified +/// address now lands in the Ironwood pool, so an Orchard-only count would never +/// grow on a new receive and the address would never rotate — silently reusing +/// one address across payments. +pub fn count_received_notes( data_dir: &Path, group_id: &str, network: WalletNetwork, @@ -1353,9 +1557,12 @@ pub fn count_orchard_received_notes( } let conn = open_readonly_connection(&db_path, db_key)?; let count: i64 = conn - .query_row("SELECT COUNT(*) FROM orchard_received_notes", [], |row| { - row.get(0) - }) + .query_row( + "SELECT (SELECT COUNT(*) FROM orchard_received_notes) \ + + (SELECT COUNT(*) FROM ironwood_received_notes)", + [], + |row| row.get(0), + ) .map_err(|e| CoreError::Crypto(format!("count received notes: {e}")))?; Ok(count.max(0) as u64) } @@ -1411,65 +1618,77 @@ pub fn wallet_notes( .flatten(); let tip = tip.unwrap_or(0); - let mut stmt = conn - .prepare( + // Post-NU6.3 a group holds notes in two pools: the sealed Orchard pool and + // the Ironwood pool that all new value (and migrated funds) land in. The two + // tables are structurally identical, so query each with the same shape and + // merge. Table/column names are compile-time constants, not user input, so + // interpolating them into the SQL is safe. + let mut notes = Vec::new(); + for (notes_table, spends_table, fk_col) in [ + ("orchard_received_notes", "orchard_received_note_spends", "orchard_received_note_id"), + ("ironwood_received_notes", "ironwood_received_note_spends", "ironwood_received_note_id"), + ] { + let sql = format!( "SELECT t.txid, orn.value, orn.is_change, orn.memo, t.mined_height, \ MAX(CASE WHEN spend_t.mined_height IS NOT NULL THEN 1 ELSE 0 END) AS spent_mined, \ - MAX(CASE WHEN s.orchard_received_note_id IS NOT NULL THEN 1 ELSE 0 END) AS has_spend \ - FROM orchard_received_notes orn \ + MAX(CASE WHEN s.{fk_col} IS NOT NULL THEN 1 ELSE 0 END) AS has_spend \ + FROM {notes_table} orn \ JOIN transactions t ON orn.transaction_id = t.id_tx \ - LEFT JOIN orchard_received_note_spends s ON s.orchard_received_note_id = orn.id \ + LEFT JOIN {spends_table} s ON s.{fk_col} = orn.id \ LEFT JOIN transactions spend_t ON spend_t.id_tx = s.transaction_id \ WHERE orn.account_id = ?1 \ - GROUP BY orn.id \ - ORDER BY orn.value DESC", - ) - .map_err(|e| CoreError::Crypto(format!("prepare notes query: {e}")))?; - - let rows = stmt - .query_map([account_id], |row| { - Ok(( - row.get::<_, Vec>(0)?, - row.get::<_, u64>(1)?, - row.get::<_, i64>(2)?, - row.get::<_, Option>>(3)?, - row.get::<_, Option>(4)?, - row.get::<_, i64>(5)?, - row.get::<_, i64>(6)?, - )) - }) - .map_err(|e| CoreError::Crypto(format!("execute notes query: {e}")))?; + GROUP BY orn.id" + ); + let mut stmt = conn + .prepare(&sql) + .map_err(|e| CoreError::Crypto(format!("prepare notes query: {e}")))?; - let mut notes = Vec::new(); - for row in rows { - let (mut txid_bytes, value, is_change, memo_bytes, received_height, spent_mined, has_spend) = - row.map_err(|e| CoreError::Crypto(format!("note row: {e}")))?; - // A note spent in a mined transaction is gone — not part of the balance. - if spent_mined == 1 { - continue; + let rows = stmt + .query_map([account_id], |row| { + Ok(( + row.get::<_, Vec>(0)?, + row.get::<_, u64>(1)?, + row.get::<_, i64>(2)?, + row.get::<_, Option>>(3)?, + row.get::<_, Option>(4)?, + row.get::<_, i64>(5)?, + row.get::<_, i64>(6)?, + )) + }) + .map_err(|e| CoreError::Crypto(format!("execute notes query: {e}")))?; + + for row in rows { + let (mut txid_bytes, value, is_change, memo_bytes, received_height, spent_mined, has_spend) = + row.map_err(|e| CoreError::Crypto(format!("note row: {e}")))?; + // A note spent in a mined transaction is gone — not part of the balance. + if spent_mined == 1 { + continue; + } + txid_bytes.reverse(); + let confirmations = match received_height { + Some(h) if tip as u64 >= h => tip as u64 - h + 1, + _ => 0, + }; + let status = if received_height.is_none() { + "pending" // incoming, not yet mined + } else if has_spend == 1 { + "spending" // a broadcast-but-unmined send is consuming it + } else { + "spendable" + }; + notes.push(NoteRecord { + received_txid: hex::encode(&txid_bytes), + value_zatoshis: value, + status: status.to_string(), + received_height, + confirmations, + is_change: is_change != 0, + memo: memo_bytes.as_deref().and_then(decode_zcash_memo), + }); } - txid_bytes.reverse(); - let confirmations = match received_height { - Some(h) if tip as u64 >= h => tip as u64 - h + 1, - _ => 0, - }; - let status = if received_height.is_none() { - "pending" // incoming, not yet mined - } else if has_spend == 1 { - "spending" // a broadcast-but-unmined send is consuming it - } else { - "spendable" - }; - notes.push(NoteRecord { - received_txid: hex::encode(&txid_bytes), - value_zatoshis: value, - status: status.to_string(), - received_height, - confirmations, - is_change: is_change != 0, - memo: memo_bytes.as_deref().and_then(decode_zcash_memo), - }); } + // Largest notes first, across both pools. + notes.sort_by(|a, b| b.value_zatoshis.cmp(&a.value_zatoshis)); Ok(notes) } @@ -1499,30 +1718,40 @@ pub fn wallet_history( let mut records: Vec = Vec::new(); // ── Received ──────────────────────────────────────────────────────────── - // Orchard notes for our account that are not change (is_change = 0 means + // Shielded notes for our account that are not change (is_change = 0 means // this note arrived in a transaction that we did NOT also spend from — - // i.e., someone else sent us funds). Group by transaction so one tx = one - // history entry, sum the note values, and pick the first real memo. + // i.e., someone else sent us funds). Post-NU6.3 a receive lands in the + // Ironwood pool while legacy receipts are in Orchard, so union both note + // tables (identical columns) before grouping — one tx = one history entry, + // even if a tx somehow deposited into both pools. Sum the note values, pick + // the first real memo. { + // A derived table unioning both pools' non-dummy columns. Table names are + // compile-time constants, so this static SQL carries no injection risk. + const RECEIVED_NOTES_UNION: &str = "( \ + SELECT transaction_id, account_id, value, is_change, memo FROM orchard_received_notes \ + UNION ALL \ + SELECT transaction_id, account_id, value, is_change, memo FROM ironwood_received_notes )"; + let sql = format!( + "SELECT t.txid, t.mined_height, b.time, SUM(rn.value), \ + ( SELECT rn2.memo \ + FROM {RECEIVED_NOTES_UNION} rn2 \ + WHERE rn2.transaction_id = t.id_tx \ + AND rn2.account_id = ?1 \ + AND rn2.is_change = 0 \ + AND rn2.memo IS NOT NULL \ + LIMIT 1 ), \ + ( SELECT vt.fee_paid FROM v_transactions vt WHERE vt.txid = t.txid LIMIT 1 ) \ + FROM {RECEIVED_NOTES_UNION} rn \ + JOIN transactions t ON rn.transaction_id = t.id_tx \ + LEFT JOIN blocks b ON b.height = t.mined_height \ + WHERE rn.account_id = ?1 AND rn.is_change = 0 \ + GROUP BY t.id_tx \ + HAVING SUM(rn.value) > 0 \ + ORDER BY t.mined_height DESC NULLS LAST" + ); let mut stmt = conn - .prepare( - "SELECT t.txid, t.mined_height, b.time, SUM(orn.value), \ - ( SELECT orn2.memo \ - FROM orchard_received_notes orn2 \ - WHERE orn2.transaction_id = t.id_tx \ - AND orn2.account_id = ?1 \ - AND orn2.is_change = 0 \ - AND orn2.memo IS NOT NULL \ - LIMIT 1 ), \ - ( SELECT vt.fee_paid FROM v_transactions vt WHERE vt.txid = t.txid LIMIT 1 ) \ - FROM orchard_received_notes orn \ - JOIN transactions t ON orn.transaction_id = t.id_tx \ - LEFT JOIN blocks b ON b.height = t.mined_height \ - WHERE orn.account_id = ?1 AND orn.is_change = 0 \ - GROUP BY t.id_tx \ - HAVING SUM(orn.value) > 0 \ - ORDER BY t.mined_height DESC NULLS LAST", - ) + .prepare(&sql) .map_err(|e| CoreError::Crypto(format!("prepare receive query: {e}")))?; let rows = stmt @@ -1743,12 +1972,23 @@ mod tests { } #[test] - fn default_birthday_is_testnet_only() { + fn new_wallets_start_at_the_tip_on_both_networks() { + // A brand-new group holds no pre-creation funds, so with no requested or + // recorded birthday it starts at the chain tip (None -> tip) rather than + // scanning hundreds of thousands of blocks of empty history. The testnet + // deep-rescan floor is opt-in via `birthday_height`, never a default. + assert_eq!(default_birthday_height(WalletNetwork::Test), None); + assert_eq!(default_birthday_height(WalletNetwork::Main), None); + assert_eq!(resolve_scan_from(None, TEST_NU5, 4_200_000), 4_200_000); + } + + #[test] + fn explicit_deep_rescan_floor_is_honoured_when_requested() { + // Passing DEFAULT_TESTNET_BIRTHDAY explicitly (an opt-in deep rescan) + // still scans from that floor when it sits inside [NU5, tip]. assert_eq!( - default_birthday_height(WalletNetwork::Test), - Some(DEFAULT_TESTNET_BIRTHDAY) + resolve_scan_from(Some(DEFAULT_TESTNET_BIRTHDAY), TEST_NU5, 4_200_000), + DEFAULT_TESTNET_BIRTHDAY ); - // A fixed height would be in mainnet's future; it starts at the tip. - assert_eq!(default_birthday_height(WalletNetwork::Main), None); } } diff --git a/src-tauri/src/commands/wallet.rs b/src-tauri/src/commands/wallet.rs index 81a3643..895947e 100644 --- a/src-tauri/src/commands/wallet.rs +++ b/src-tauri/src/commands/wallet.rs @@ -225,8 +225,9 @@ pub async fn wallet_sync(state: State<'_, AppState>, group_id: String) -> AppRes } } + let batch_size = state.load_settings().sync_batch_size; let result = wallet::sync_group( - &state.data_dir, &group_id, network, &url, db_key.as_ref(), &cancel, + &state.data_dir, &group_id, network, &url, db_key.as_ref(), batch_size, &cancel, ) .await; @@ -306,7 +307,7 @@ async fn resolve_receive_address( let (network, _url, _ufvk) = group_wallet_ctx(state, group_id).await?; let db_key = state.wallet_db_key(group_id).await?; let current_notes = - wallet::count_orchard_received_notes(&state.data_dir, group_id, network, db_key.as_ref())?; + wallet::count_received_notes(&state.data_dir, group_id, network, db_key.as_ref())?; let mut settings = state.load_settings(); let entry = settings.receive_state.entry(group_id.to_string()).or_default(); @@ -409,7 +410,7 @@ pub async fn wallet_send( if draft.spends.is_empty() { return Err(AppError::new( "wallet", - "the transaction has no Orchard spends to sign", + "the transaction has no shielded spends to sign", )); } let message = hex::decode(draft.sighash_hex.trim()) @@ -422,9 +423,9 @@ pub async fn wallet_send( .map(|s| { let alpha = hex::decode(s.alpha_hex.trim()) .map_err(|e| AppError::new("wallet", format!("alpha: {e}")))?; - Ok((s.index, alpha)) + Ok((s.pool, s.index, alpha)) }) - .collect::)>>>()?; + .collect::)>>>()?; // 2. Shared coordinator inputs (everything but the per-spend randomizer). let (group, server_url) = @@ -513,7 +514,7 @@ pub async fn wallet_send( // Multi-spend transactions use this same total budget across all spends. const SIGNING_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(35 * 60); - let signing_result: Result, String> = { + let signing_result: Result, String> = { let total = spends.len(); // Sign each note in its own re-randomized FROST session, one note at @@ -527,8 +528,9 @@ pub async fn wallet_send( // Atomic: the first note to fail/reject returns Err before any // broadcast, so a partially-signed transaction is never produced. let signing_fut = async { - let mut signatures: Vec<(usize, String)> = Vec::with_capacity(total); - for (i, (index, alpha)) in spends.into_iter().enumerate() { + let mut signatures: Vec<(wallet::SpendPool, usize, String)> = + Vec::with_capacity(total); + for (i, (pool, index, alpha)) in spends.into_iter().enumerate() { // Tell the UI which note is being signed; each is a separate // approval in signers' inboxes. let _ = task_app.emit( @@ -564,7 +566,9 @@ pub async fn wallet_send( send_context, }; match run_coordinator(suite, params, tx.clone(), cancel.clone()).await { - Ok(output) => signatures.push((index, hex::encode(&output.signature))), + Ok(output) => { + signatures.push((pool, index, hex::encode(&output.signature))) + } Err(e) => return Err(e.to_string()), // abort remaining notes } } @@ -598,7 +602,7 @@ pub async fn wallet_send( }; let signed_pczt_hex = - match wallet::apply_orchard_signatures(&pczt_hex, &sighash_hex, signatures) { + match wallet::apply_signatures(&pczt_hex, &sighash_hex, signatures) { Ok(hex) => hex, Err(e) => return fail(e.to_string()), }; diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index 74e73f9..d4e4d6e 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -65,6 +65,11 @@ pub struct Settings { /// scans the blocks that funded the group, so the balance reads zero. #[serde(default)] pub wallet_birthdays: HashMap, + /// Blocks downloaded and scanned per sync batch. `None` uses the core + /// default; larger values reduce per-batch overhead on slow links at the + /// cost of memory. Clamped by the core to a sane range. + #[serde(default)] + pub sync_batch_size: Option, /// Active session profile: "coordinator" or "participant". Toggled by the /// sidebar profile switch; drives which saved configuration is in use. #[serde(default)] diff --git a/src/ipc/commands.ts b/src/ipc/commands.ts index 9260e82..aa3fe61 100644 --- a/src/ipc/commands.ts +++ b/src/ipc/commands.ts @@ -128,12 +128,15 @@ export interface PoolBalance { export interface WalletStatus { initialized: boolean; address: string | null; - /** Aggregate totals (kept for back-compat; equal to the Orchard pool). */ + /** Aggregate totals across *all* pools — the sum of the sealed `orchard` pool + * and the new `ironwood` pool, not the Orchard pool alone. */ total_zatoshis: number; spendable_zatoshis: number; - /** Per-pool breakdown. With an Orchard-only group UFVK, sapling & transparent - * are 0 — the threshold group cannot hold or spend those pools. */ + /** Per-pool breakdown. `orchard` is the sealed legacy pool (spendable but can + * never receive again); `ironwood` is where new shielded value lands + * post-NU6.3. sapling & transparent are 0 for an Orchard/Ironwood group. */ orchard: PoolBalance; + ironwood: PoolBalance; sapling: PoolBalance; transparent: PoolBalance; synced_height: number; @@ -205,6 +208,9 @@ export const walletNewReceiveAddress = (groupId: string) => invoke("wallet_new_receive_address", { groupId }); export interface SpendToSign { + /** Which pool's bundle holds this spend. Post-NU6.3 one transaction can carry + * both (a turnstile send spends Orchard notes but delivers via Ironwood). */ + pool: "orchard" | "ironwood"; index: number; alpha_hex: string; } diff --git a/src/screens/Groups.tsx b/src/screens/Groups.tsx index d3bf5dd..9f839fc 100644 --- a/src/screens/Groups.tsx +++ b/src/screens/Groups.tsx @@ -220,12 +220,13 @@ function validateRecipient( return null; } -/** Receive / shield-into-group card: shows the group's *rotating* Orchard - * unified address. Each address is a fresh diversifier of the same viewing key +/** Receive / shield-into-group card: shows the group's *rotating* unified + * address. Each address is a fresh diversifier of the same viewing key * (#3), so incoming payments aren't linkable by a reused address. The address * auto-advances once the group has received new notes; the user can also force * a fresh one. "Shielding" into the group means sending to this address from a - * personal wallet — the group then holds the funds as spendable Orchard. */ + * personal wallet — post-NU6.3 the group then holds the funds as spendable + * Ironwood. */ function ReceiveShieldCard({ groupId, fallback }: { groupId: string; fallback: string | null }) { const queryClient = useQueryClient(); const [copied, setCopied] = useState(false); @@ -245,9 +246,9 @@ function ReceiveShieldCard({ groupId, fallback }: { groupId: string; fallback: s

Receive / Shield into group

Send Zcash to this unified address to fund the group. Funds arrive in the - group's shielded Orchard pool and become spendable by the - threshold. To shield transparent funds, send them here - from a personal wallet — the receive itself is the shielding step. + group's shielded Ironwood pool and become spendable by + the threshold. To shield transparent funds, send them + here from a personal wallet — the receive itself is the shielding step.