diff --git a/.config/nextest.toml b/.config/nextest.toml index 6d0425d5b..33f526460 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -59,6 +59,8 @@ not ( | package(focused-fuel-guest) | package(focused-fuel-harness) | package(focused-fuel-protocol) + | package(rumors-budget-curves) + | package(rumors-netperf) | package(fuzzfit-guest) | package(fuzzfit-harness) | package(suanpan-fuel-guest) @@ -95,12 +97,3 @@ slow-timeout = { period = "60s", terminate-after = 9 } # while the job sets none. [profile.high-count] slow-timeout = { period = "60s" } - -# The window measurement suites (window_knee, window_operator, -# window_corners, gossip_pipelining) need no scheduling isolation: their -# pins assert on exact virtual wire time (`benches/support/latency.rs`), -# which machine load cannot move, so they run interleaved with the rest -# of the suite like any other test. The one wall-clock upper bound among -# them (window_corners' real-clock promptness cross-check) holds a -# ~0.5 s measured catch-up under a 5 s budget: that ~8x headroom is what -# absorbs load there, where the virtual pins need none. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0b23cbbd..760446ef1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,14 +3,15 @@ # `ci` is the build-everything tier — lints, docs, the feature matrix, the # full test and doctest run, bench compilation, fuzz-target verification, and # the viz bundle; -# the justfile's `ci` recipe line is the roster of record, ordered +# the justfile's `ci` recipe line names every leg this job runs, ordered # cheap-first. It builds the fuzz targets but does not run the smoke (`just all` # adds that locally — libFuzzer minutes are a poor per-commit spend). The # `instruments` job beside it re-runs the gate judgments that belong on a # shared runner: dependency policy, the board verdicts and pins, and surface # totality. Its job comment says which instruments stay local and why. -# The `properties` job runs Rumors in release at the larger case count pinned -# by `test-release` in the justfile. +# The `properties` job runs Rumors in release codegen, with overflow checks +# and debug assertions, at the larger case count pinned by `test-release` in +# the justfile. # The justfile owns each job's roster. The workflow names only those groups, # so adding or removing a check cannot leave a copied workflow list behind. # diff --git a/.gitignore b/.gitignore index 3003a6ceb..92c9f87d0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ formal/lean/.lake/ formal/quint/node_modules/ formal/quint/_apalache-out/ -# Fetched TLC binary; the sha256 pin alongside it is the artifact of record. +# Fetched TLC binary; only the sha256 pin alongside it is tracked. formal/tla/tla2tools.jar # EventDag analysis dumps (lake exe eventdag); regenerable from the tool. diff --git a/AGENTS.md b/AGENTS.md index bbbef9135..9d33accf9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,8 @@ # rumors — project notes -A guidepost, not a manual: it orients and points, and the documentation of -record is the rustdoc. Keep this file small and accurate; when detail needs a -durable home, put it in the docs and point there. +A guidepost, not a manual: it orients and points, and the rustdoc holds the +documentation. Keep this file small and accurate; when detail needs a durable +home, put it in the docs and point there. ## Orientation @@ -22,11 +22,16 @@ tour, and the comment above each recipe says what it checks and why. `just fmt`. - After editing crate-level rustdoc, run `just readme`: the READMEs are derived, never hand-edited. -- Before committing, get the checks that can read the change fully clean: - `just gate` for anything that can alter what builds or runs, its - build-free tier `just gate-lints` for a change confined to plain comments - and test doc comments, and nothing for a commit-message rewrite. The - comment above the `gate` recipe gives the reasoning. +- Choose verification by what your diff can break: the comment above each + recipe says what it checks. Before a commit, run the recipes that check + what you touched. A change that can alter what builds or runs needs at + least `just clippy` and the affected tests; a change confined to plain + comments and test doc comments needs only the build-free tier + `just gate-lints`; a rewrite of a commit message alone needs no check. +- Get `just gate` fully clean on the tip proposed for `main`, and on every + commit `main`'s first-parent line gains: its merges, and commits made + directly on `main`. Commits inside a merged branch need not each pass the + gate; first-parent bisection (below) is what makes that safe. - After a gate leg fails, fix it and rerun that leg and any leg the fix can reach, not the whole gate: the legs that passed still hold for what they read. @@ -45,7 +50,7 @@ justfile's `nightly_toolchain` give the reason and the bump procedure. - Unit and protocol tests live in a sibling file: `mod tests;` in the source, `tests.rs` next to it. Cross-peer suites are binaries in `tests/`, built on - the fixtures in `crates/rumors-testkit` (its `common` module doc maps them). + the fixtures in `crates/rumors-testkit` (its `common` module doc describes them). - Give every test a doc comment stating the behavior and invariant it protects. The gate's `testdoc` checks that the comment exists; review holds it to the standard. @@ -91,17 +96,20 @@ No gate leg checks these; review does. - Nothing in the tree refers to code that no longer exists: no "formerly", no "was removed", no deleted API names. Restate prose in terms of what is; provenance lives in git history. -- Code may cite the Lean artifact by *theorem or definition name*, never by - file path, when a kernel-checked statement backs the claim, and still states - the invariant inline. -- The model of record is uniform-hash and authenticated-honest-peer: the +- The assumed model is uniform-hash and authenticated-honest-peer: the transport is pre-authenticated and authorized, and an authorized peer already holds write authority over the set. Hostile peers are off-model, so no - design or cost argument rests on adversary economics, and fail-fast checks - detect conformance bugs rather than enforce security. Add no machinery to - guarantee termination against non-conforming peers or links (applications - own deadlines for those waits); preserve progress under conforming traffic - and propagate detected failures promptly. + design or cost argument rests on a hostile peer's economics, and fail-fast + checks detect conformance bugs rather than enforce security. An adversary + outside the peers is in model: it observes the transport, steers gossip + timing and topology (cutting connections included), and triggers + insertions and redactions through the application, but cannot alter a + session or make a peer depart from the protocol. The protocol's integrity + must not depend on the transport's confidentiality, nor on that adversary + being unable to infer replica contents or versions. Add no machinery to + guarantee termination against non-conforming peers or connections + (applications own deadlines for those waits); preserve progress under + conforming traffic and propagate detected failures promptly. - Never let two independently `seed`ed universes interact. Within a universe, the linearity of parties is the invariant everything rests on (see `before`'s `Party` docs). @@ -109,10 +117,10 @@ No gate leg checks these; review does. so reason about it in version ceilings and floors, not markers. - The `insta` snapshots and the exact byte counts in `tests/protocol_overhead.rs` pin the wire and storage formats. Re-accept - them only for a deliberate, owner-ruled change to a format or to the capture - renderer, named in the re-accepting commit, never to accommodate drift. Once - a release ships, a wire format change means a new protocol version, never a - mutation of a released one. + them only for a deliberate change to a format or to the capture renderer, + named in the re-accepting commit, never to accommodate drift. Once a release + ships, a wire format change means a new protocol version, never a mutation + of a released one. - A bookmark snapshot that moves because the encoding changed is an on-disk format change: bump `BOOKMARK_FORMAT_VERSION` in the same commit. - A snapshot that moves only because its test fixture changed is a fixture diff --git a/Cargo.lock b/Cargo.lock index e1f5cebda..fd132cc61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,43 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" +dependencies = [ + "crypto-common 0.2.2", + "inout", +] + +[[package]] +name = "aes" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fc36d7440d015b45468ba08a21e80e056ebbd014c611c6298bb7503e04bd1" +dependencies = [ + "cipher", + "cpubits", + "cpufeatures 0.3.1", + "zeroize", +] + +[[package]] +name = "aes-gcm" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ctutils", + "ghash", + "zeroize", +] + [[package]] name = "ahash" version = "0.8.12" @@ -31,9 +68,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -45,6 +82,15 @@ dependencies = [ "proptest", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -93,7 +139,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -104,7 +150,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -115,9 +161,48 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arbitrary" -version = "1.4.2" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bc62ac97cc33321f50863d514c3bc38a453947a8f9e781137e47c7401020aed" + +[[package]] +name = "asn1-rs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure 0.13.2", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] name = "async-stream" @@ -138,7 +223,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -149,7 +234,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -158,11 +243,17 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + [[package]] name = "base64" -version = "0.22.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "before" @@ -178,12 +269,12 @@ dependencies = [ "hex", "indicatif", "insta", - "num-bigint", + "num-bigint 0.5.1", "peak_alloc", "postcard", "proptest", - "rand 0.9.4", - "rand_chacha 0.9.0", + "rand 0.10.3", + "rand_chacha 0.10.0", "rayon", "serde", "serde_bytes", @@ -207,12 +298,12 @@ dependencies = [ "indicatif", "libm", "mimalloc", - "num-bigint", + "num-bigint 0.5.1", "num-traits", "plotters", "proptest", - "rand 0.8.8", - "rand_chacha 0.3.1", + "rand 0.10.3", + "rand_chacha 0.10.0", "rayon", "serde", "serde_json", @@ -233,24 +324,49 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.8.0" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d87354e4229f54a44f7bf2435906a4656dba36026ab6eaca629a2c436a691c" +dependencies = [ + "bit-vec 0.10.1", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" dependencies = [ - "bit-vec", + "serde", ] [[package]] name = "bit-vec" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "5727b15fa97d4f4fee0a3b7c3d550ed0269f54329207b86388de918604e31269" +dependencies = [ + "borsh", + "serde", +] [[package]] name = "bitflags" -version = "2.12.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] [[package]] name = "block-buffer" @@ -261,6 +377,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", + "zeroize", +] + [[package]] name = "board-fuel-guest" version = "0.0.0" @@ -278,16 +404,53 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "bon" +version = "3.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05442cd7005532d0cfedec676b5b9333d2b4c7c3afabe2b1a9ce2742fbe2ee6" +dependencies = [ + "bon-macros", +] + +[[package]] +name = "bon-macros" +version = "3.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93833e97ac7c46ba97045afcf247238c27057538fcf2f06344662ddd5f567be6" +dependencies = [ + "darling", + "ident_case", + "prettyplease", + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "borsh" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" dependencies = [ + "borsh-derive", "bytes", "cfg_aliases", ] +[[package]] +name = "borsh-derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "bs58" version = "0.5.1" @@ -308,9 +471,9 @@ dependencies = [ [[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", ] @@ -331,7 +494,7 @@ dependencies = [ "data-encoding", "half", "nom", - "num-bigint", + "num-bigint 0.4.8", "num-rational", "num-traits", "separator", @@ -341,9 +504,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.62" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "375989decec1a0fa424442bed520fa12ede43a48475ce8c7417d2c69b32b5f6b" dependencies = [ "find-msvc-tools", "shlex", @@ -351,15 +514,26 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", +] [[package]] name = "chrono" @@ -397,11 +571,22 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", + "inout", +] + [[package]] name = "clap" -version = "4.6.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -409,33 +594,40 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", + "terminal_size", ] [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", ] [[package]] name = "clap_lex" -version = "1.1.0" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "cmov" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "cobs" @@ -454,14 +646,14 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "console" -version = "0.16.3" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" dependencies = [ "encode_unicode", "libc", "unicode-width", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -480,6 +672,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + [[package]] name = "cpp_demangle" version = "0.5.1" @@ -489,6 +687,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -509,27 +713,27 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c7459262c93a3c408bda96acaaa3d92868f166b33d445b20921f8378325038" +checksum = "80552083a2db143c5d951debe9f59a7d9f22084c70abe450fed5220060fa26c3" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a25bfba0da265ef1f98728358e9bb3ab7489913e7bd759c743108892288934" +checksum = "7cf84b7e5f0aa42cb0d55cabf01c520fdb70a50d8b572a841ee875083589d643" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a9ad33269057337a70db66950f426fbdce436a66fe8071f55851a13a2e40cd" +checksum = "81d47ec2358cdbace0520ac212c003656b529f0c60e43fbbe9a331632cd9e8fc" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -537,9 +741,9 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d322e6584efe3b229b1164b49edf55aec561553426f7fe3e228a45e80a15a190" +checksum = "eebb94b54db96b26e387bc8c698823d83d9254d551a6ed846a60cebf62ed7135" dependencies = [ "serde", "serde_derive", @@ -548,9 +752,9 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7b9f73f97da69d6edc9adbfeec068cdb2649f0221be41abd3909267cb1cd53" +checksum = "be81b89cb7b186a26cf2014c312aeb17737da988b4444d16a0cb3424d637d44e" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -571,7 +775,7 @@ dependencies = [ "rustc-hash", "serde", "serde_derive", - "sha2", + "sha2 0.10.9", "smallvec", "target-lexicon", "wasmtime-internal-core", @@ -579,9 +783,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7015ef10993d7129e0bce933874b60dab8187239aca4ceca352987d9907d528" +checksum = "cb1b64a509c3814932fb9845ce8da835cd10d62c6c56dacfdcd9af389d3bf313" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -592,24 +796,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37916b08a7b17e063bae743cb746da542df7df283ced961aae213620dc11e27a" +checksum = "e667a0e9ed3bbbed0e7e52cd2dea85a645745b39f547097e2fca0bf317cac9df" [[package]] name = "cranelift-control" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8154d189f2cc2a84a95a8129773799ddcf2f4609f667047db30715db4be6aa0a" +checksum = "a5fa7d5123705226a368b6b1c7b10f23036c35e8041ffdd5f6505790f5c31404" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccbd0c43e96db753f44a84e44f680f9423ed0a475b81f301ba7c44b5db52c37b" +checksum = "a1bffb83ac1d7052691d1710ca8eb334d4fcaad363e589f2b89d38d97bda5776" dependencies = [ "cranelift-bitset", "serde", @@ -619,9 +823,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b28ae2961cdda7a6814431b40e87bee46e57b7f92294467b32f447108e14674" +checksum = "1bc727c856bf57eae76c72ac4f9b1eaf49947a2b02f699798262fc8399557b7a" dependencies = [ "cranelift-codegen", "hashbrown 0.17.1", @@ -632,57 +836,57 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41eef45b50970e024d673e3fc4a0703e4fee75ca31d63b26566eb0f142300179" +checksum = "a92e743f35915d55cd3d3178aab483661f78c2f9274aa704f29be69e3789c5bd" [[package]] name = "cranelift-native" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "649c7b9ad93d5d92287fee74608cacfb139602116293a46e2f25e6ea5402f05c" +checksum = "127c50e5e2b2b97116d4e2c079db6ce29b07303cd1ab48a8bb4c2abbf16a7a68" dependencies = [ "cranelift-codegen", "libc", + "mach2", "target-lexicon", ] [[package]] name = "cranelift-srcgen" -version = "0.135.8" +version = "0.137.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da04416d8e400ad7ae6d9722db72bfbddfbf36d0ff528ec422c4cc336621a172" +checksum = "6f34b169b8cbbaed2b4995205f1d02d7eac4b2771df5479255fe5483e1334a39" [[package]] name = "crc32fast" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +checksum = "5f97d3416d5337d15c4b0d78c8c91df922ca143f57ec20e2d1c188333047ef04" dependencies = [ "cfg-if", ] [[package]] name = "criterion" -version = "0.5.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" dependencies = [ + "alloca", "anes", "cast", "ciborium", "clap", "criterion-plot", - "is-terminal", - "itertools 0.10.5", + "itertools 0.13.0", "num-traits", - "once_cell", "oorandom", + "page_size", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -690,19 +894,19 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" dependencies = [ "cast", - "itertools 0.10.5", + "itertools 0.13.0", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -710,18 +914,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.20" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crunchy" @@ -729,6 +933,21 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c035cb64cba03dad2fb921f3e218785e8cf9a41790da5eb3a1400f62fa2be11" +dependencies = [ + "cpubits", + "ctutils", + "hybrid-array", + "num-traits", + "rand_core 0.10.1", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -746,6 +965,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", + "rand_core 0.10.1", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "ctr" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" +dependencies = [ + "cipher", +] + +[[package]] +name = "ctutils" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261af4dc7a06ea8a527a8717d8cbba3417530d6ea14e1edb3de6b67806be474f" +dependencies = [ + "cmov", + "subtle", +] + +[[package]] +name = "darling" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 3.0.9", +] + +[[package]] +name = "darling_macro" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" +dependencies = [ + "darling_core", + "quote", + "syn 3.0.9", ] [[package]] @@ -754,13 +1048,43 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" +[[package]] +name = "der" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a996a108feb8b427a6e12fcf6af4aa83409b79d72c15337d7741368131ee004" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.8", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e" + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "crypto-common 0.1.7", ] @@ -770,8 +1094,43 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ + "block-buffer 0.12.1", "const-oid", "crypto-common 0.2.2", + "ctutils", + "zeroize", +] + +[[package]] +name = "dirs" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d57d423b3c82e89b9a24ca3091fee61f456a26edbd28d26c65906f4bc1dcd8f" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", ] [[package]] @@ -782,7 +1141,7 @@ checksum = "ad5208a115eaba24916f7456929832e310a81518c641f93fee4f89aa93aa3675" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -796,9 +1155,29 @@ dependencies = [ [[package]] name = "either" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "elliptic-curve" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900f37e7e18d74a2347389af6cd69e3a30d5cc9e697f40004865679aa75e9c7c" +dependencies = [ + "base16ct", + "crypto-bigint", + "crypto-common 0.2.2", + "digest 0.11.3", + "ff", + "group", + "hkdf", + "hybrid-array", + "rand_core 0.10.1", + "sec1", + "subtle", + "zeroize", +] [[package]] name = "embedded-io" @@ -820,9 +1199,9 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" [[package]] name = "errno" @@ -831,20 +1210,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "ff" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" +dependencies = [ + "rand_core 0.10.1", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" [[package]] name = "flate2" @@ -870,7 +1265,7 @@ dependencies = [ "before", "dlmalloc", "focused-fuel-protocol", - "num-bigint", + "num-bigint 0.5.1", "spin", ] @@ -896,6 +1291,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "fork" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafa2fb0e6b3b0886eb36b909c13a5e3dc9d7e0cf436376e43f095177050c029" +dependencies = [ + "libc", +] + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -906,11 +1310,17 @@ dependencies = [ ] [[package]] -name = "futures" -version = "0.3.32" +name = "funty" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ "futures-channel", "futures-core", "futures-io", @@ -921,9 +1331,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -931,44 +1341,44 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", ] [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -1023,14 +1433,24 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi", - "wasip2", + "rand_core 0.10.1", +] + +[[package]] +name = "ghash" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" +dependencies = [ + "polyval", + "zeroize", ] [[package]] @@ -1045,6 +1465,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "group" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" +dependencies = [ + "ff", + "rand_core 0.10.1", + "subtle", +] + [[package]] name = "half" version = "2.7.1" @@ -1085,56 +1516,169 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + +[[package]] +name = "hpke" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f512e325a1a71bf3273fb9b7fc9e5d96dac136fb4a95d0e6637001b12ea3e09" +dependencies = [ + "aead", + "aes-gcm", + "getrandom 0.4.3", + "hkdf", + "hybrid-array", + "p256", + "p384", + "p521", + "rand_core 0.10.1", + "sha2 0.11.1", + "subtle", + "zeroize", +] + [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ + "subtle", "typenum", + "zeroize", ] [[package]] -name = "idna" -version = "1.1.0" +name = "icu_collections" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "fe090a42a0d3140fed8c63263ed1fecc02422cb2f4bfe55cd8de2de1b8e105dd" dependencies = [ - "idna_adapter", - "smallvec", + "displaydoc", + "potential_utf", "utf8_iter", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "idna_adapter" -version = "1.1.0" +name = "icu_locale_core" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25d29b57c17c6528d0dc4c2141cfa2d08200465acb537a3909c8b9b8a4a984c0" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404a3b8c486f205c87fe7f23ab6894d84a4ad76d6e4671ae1981ba7def87c599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20f0088bfb7441f7a37fa0c9e20cb1e9cba1cac6b9ce8cd2a6dc44294f8e8cbc" + +[[package]] +name = "icu_properties" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ea83d991c56158f7cf898bf86436c1dfe7c07ee82fe88951f2695c9f37a379f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98f29af82d02b163fe50161388350e743bb3107cc8e8c2f7314cb505faddfcf" + +[[package]] +name = "icu_provider" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279259b0ac81c89d11c290495fdcfa96ea3643b7df311c138b6fe8ca5237f0f8" +checksum = "413099315636c588ee8f011190b329b971a09a8fae9d157e01dcae8379468514" dependencies = [ - "idna_mapping", - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] [[package]] -name = "idna_mapping" +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c13906586a4b339310541a274dd927aff6fcbb5b8e3af90634c4b31681c792" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ - "unicode-joining-type", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1151,9 +1695,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.5" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f007684f2e9727160da8b960ec161264703bfd1af084fd2e34d040c9a0dd4" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", "portable-atomic", @@ -1163,26 +1707,24 @@ dependencies = [ ] [[package]] -name = "insta" -version = "1.47.2" +name = "inout" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094e" +checksum = "3b5cf4372d022092674a83b8febf5865f7a573cc0c5baec5e49c879b6a20978f" dependencies = [ - "console", - "once_cell", - "similar", - "tempfile", + "hybrid-array", ] [[package]] -name = "is-terminal" -version = "0.4.17" +name = "insta" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +checksum = "b67d3d2e287e4b86c10b3f3b641033d1f89b74bdb39d05f34952e2b9a6fe21cd" dependencies = [ - "hermit-abi", - "libc", - "windows-sys", + "console", + "once_cell", + "similar", + "tempfile", ] [[package]] @@ -1193,9 +1735,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -1209,6 +1751,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1217,13 +1768,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "8dc09d2154098bbf4ef54eab6b117a3c24cbbffe94046b16ee6d6d4510584d3a" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -1237,6 +1787,12 @@ dependencies = [ "cpufeatures 0.3.1", ] +[[package]] +name = "lazy_static" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" + [[package]] name = "leb128fmt" version = "0.1.0" @@ -1245,9 +1801,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" [[package]] name = "libm" @@ -1264,17 +1820,32 @@ dependencies = [ "cc", ] +[[package]] +name = "libredox" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +dependencies = [ + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + [[package]] name = "log" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c" [[package]] name = "mach2" @@ -1284,9 +1855,9 @@ checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memfd" @@ -1324,13 +1895,25 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", ] [[package]] @@ -1351,9 +1934,26 @@ checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", - "rand 0.8.8", ] +[[package]] +name = "num-bigint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" +dependencies = [ + "num-integer", + "num-traits", + "rand 0.10.3", + "rand_core 0.10.1", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-integer" version = "0.1.47" @@ -1375,7 +1975,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num-bigint", + "num-bigint 0.4.8", "num-integer", "num-traits", ] @@ -1387,13 +1987,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", +] + +[[package]] +name = "num_threads" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabcc654086861f9e1bc5115258de62ef92c79b20f4615a1b0cc57c4e82027d4" +dependencies = [ + "libc", ] [[package]] name = "object" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +checksum = "dd229a0361b9d0d4396176e02d65897f487eebeab7caa6d443855ee152ca0b9c" dependencies = [ "crc32fast", "hashbrown 0.17.1", @@ -1401,6 +2011,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1419,6 +2038,57 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "p256" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c9239b2dbc807adbbe147e8cf72ea7450c3a0aabe62cb8e75ff4ec22e1f72a" +dependencies = [ + "elliptic-curve", + "primefield", + "primeorder", +] + +[[package]] +name = "p384" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d17b851e6b3e378ab4ecb07fa2ed23f4d15f075735f8fec9fa1e7bdce5f8301f" +dependencies = [ + "elliptic-curve", + "fiat-crypto", + "primefield", + "primeorder", +] + +[[package]] +name = "p521" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad64cc32c2dc466317c12ee5853e61f159f9eab1fe7efade0395dc2e7b43449" +dependencies = [ + "base16ct", + "elliptic-curve", + "primefield", + "primeorder", +] + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "peak_alloc" version = "0.3.0" @@ -1482,14 +2152,26 @@ checksum = "ac5da421106a50887c5b51d20806867db377fbb86bacf478ee0500a912e0c113" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", +] + +[[package]] +name = "polyval" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" +dependencies = [ + "cpubits", + "cpufeatures 0.3.1", + "universal-hash", + "zeroize", ] [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "postcard" @@ -1503,6 +2185,21 @@ dependencies = [ "serde", ] +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1512,27 +2209,72 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" +dependencies = [ + "proc-macro2", + "syn 3.0.9", +] + +[[package]] +name = "primefield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4" +dependencies = [ + "crypto-bigint", + "crypto-common 0.2.2", + "ff", + "rand_core 0.10.1", + "subtle", + "zeroize", +] + +[[package]] +name = "primeorder" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c9f42978c78a00e3d68f69fc03e57a234debae69da4020a4fb588fcdcd07b06" +dependencies = [ + "elliptic-curve", + "primefield", + "wnaf", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[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", ] [[package]] name = "proptest" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +checksum = "b8530004ccb15eae51c7e40009fbe317f341f804db54dc033eec1c50be28cfa0" dependencies = [ "bit-set", - "bit-vec", + "bit-vec 0.10.1", "bitflags", + "chacha20", + "core_detect", "num-traits", - "rand 0.9.4", - "rand_chacha 0.9.0", + "rand 0.10.3", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -1542,9 +2284,9 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e6d73adcf2f76b98d3de7a31831b6d6436fd2b6518e0ad4f7cc722a12ad4133" +checksum = "64c66a82a3d48db9b7c2ba1307e06fcb81a35ba82952f58bc1bfb218321f7c0b" dependencies = [ "cranelift-bitset", "log", @@ -1554,13 +2296,13 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bde547f939ab9aa321a54c6694aef2e1e27741c2523c0627ff306677b3cbcff" +checksum = "138a9a5997d9cba5e54c7c3b836d7164f2bfe0852c7e98d5835e1708d6efdf36" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", ] [[package]] @@ -1571,18 +2313,24 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[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", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -1597,12 +2345,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.4" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -1617,12 +2366,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "3e6af7f3e25ded52c41df4e0b1af2d047e45896c2f3281792ed68a1c243daedb" dependencies = [ "ppv-lite86", - "rand_core 0.9.5", + "rand_core 0.10.1", ] [[package]] @@ -1636,20 +2385,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_distr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d431c2703ccf129de4d45253c03f49ebb22b97d6ad79ee3ecfc7e3f4862c1d8" dependencies = [ - "getrandom 0.3.4", + "num-traits", + "rand 0.10.3", ] [[package]] name = "rand_xorshift" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +checksum = "60aa6af80be32871323012e02e6e65f8a7cc7890931ae421d217ad8fe0df2ccf" dependencies = [ - "rand_core 0.9.5", + "rand_core 0.10.1", ] [[package]] @@ -1672,6 +2428,29 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.14.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8774e05a7d0de114588e6a28fe7e71694b82614ed569d86d8b389dfbc98b8ad8" +dependencies = [ + "ring", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + +[[package]] +name = "redox_users" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" +dependencies = [ + "libredox", + "thiserror", +] + [[package]] name = "regalloc2" version = "0.15.2" @@ -1689,9 +2468,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -1701,9 +2480,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -1712,40 +2491,111 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] -name = "rumors" -version = "0.1.0" +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ - "alloc-meter", - "async-stream", + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rumors" +version = "0.1.0" +dependencies = [ + "aes-gcm", + "alloc-meter", + "async-stream", "before", + "bitvec", "bytes", "cbor-diag", "ciborium", "criterion", + "fork", "futures", "hex", + "hkdf", + "hmac", + "hpke", "insta", - "itertools 0.14.0", + "itertools 0.15.0", "pollster", "proptest", - "rand 0.9.4", - "rand_chacha 0.9.0", + "rand 0.10.3", + "rand_chacha 0.10.0", + "rcgen", "rumors", "rumors-testkit", + "rustls", "schnellru", "seq-macro", "serde", + "sha2 0.11.1", "sha3", "smallvec", "tempfile", "thiserror", "tinyvec", "tokio", + "tokio-rustls", + "zeroize", +] + +[[package]] +name = "rumors-budget-curves" +version = "0.0.0" +dependencies = [ + "alloc-meter", + "clap", + "plotters", + "rayon", + "rumors", + "rumors-testkit", + "serde", + "serde_json", +] + +[[package]] +name = "rumors-netperf" +version = "0.1.0" +dependencies = [ + "anyhow", + "ciborium", + "clap", + "csv", + "dirs", + "indicatif", + "libm", + "nix", + "peak_alloc", + "plotters", + "proptest", + "rand 0.10.3", + "rand_distr", + "rcgen", + "rumors", + "rustc_version", + "rustls", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.11.1", + "sha3", + "tokio", + "tokio-rustls", + "toml", + "vergen-gitcl", ] [[package]] @@ -1757,11 +2607,10 @@ dependencies = [ "futures", "pollster", "proptest", - "rand 0.9.4", - "rand_chacha 0.9.0", + "rand 0.10.3", + "rand_chacha 0.10.0", "rumors", "serde", - "sha3", "tokio", ] @@ -1773,6 +2622,7 @@ dependencies = [ "ciborium", "hex", "rumors", + "rumors-testkit", "tokio", "tracing", ] @@ -1808,24 +2658,67 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "e5e76742e5294153d4dde1207dbec5bdd81eef6fabdc0d2118babadabfd858aa" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", ] [[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 = "rusty-fork" @@ -1839,6 +2732,12 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "same-file" version = "1.0.6" @@ -1859,6 +2758,20 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "sec1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" +dependencies = [ + "base16ct", + "ctutils", + "der", + "hybrid-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.28" @@ -1883,9 +2796,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[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", @@ -1903,29 +2816,29 @@ 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.9", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -1934,6 +2847,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_test" version = "1.0.177" @@ -1954,6 +2876,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "digest 0.11.3", +] + [[package]] name = "sha3" version = "0.12.0" @@ -1967,9 +2900,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simd-adler32" @@ -1991,21 +2924,21 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2047,14 +2980,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "suanpan" version = "0.1.0" dependencies = [ - "num-bigint", + "num-bigint 0.5.1", "proptest", ] @@ -2073,7 +3006,7 @@ name = "suanpan-fuel-harness" version = "0.0.0" dependencies = [ "board-fuel-harness", - "num-bigint", + "num-bigint 0.5.1", "proptest", "suanpan-fuel-protocol", "wasmtime", @@ -2088,6 +3021,12 @@ dependencies = [ "serde", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "surfacecheck" version = "0.1.0" @@ -2099,9 +3038,9 @@ 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", @@ -2110,15 +3049,43 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.13.5" @@ -2127,15 +3094,15 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2147,24 +3114,76 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abc840c238154d58f9e86b2792261edfde565a17696e1cda1a449de27979801a" +dependencies = [ + "displaydoc", + "zerovec", ] [[package]] @@ -2179,18 +3198,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" @@ -2204,20 +3214,81 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys", + "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.9", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" +dependencies = [ + "rustls", + "tokio", ] +[[package]] +name = "toml" +version = "1.2.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ffcdf8f50436dbbfd675c1fe1b8e0854f42b7defea8584bdebe1aee900e561" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.18+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec6e78bd70db9420d8d212fa9dc97f116448a1ceff5d00eabb991d407e21396" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.2.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009dbb7700f11c55ef83aebbe4c0e9cf1f1ac0844bd8d6f00dc38f302026e13a" + [[package]] name = "tracing" version = "0.1.44" @@ -2237,7 +3308,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2262,43 +3333,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] -name = "unicode-bidi" -version = "0.3.18" +name = "unicode-ident" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] -name = "unicode-ident" -version = "1.0.24" +name = "unicode-width" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "ca718471876992059f251e33aafc334346ada08042b7661dd1fe313a9bced557" [[package]] -name = "unicode-joining-type" -version = "1.0.0" +name = "unit-prefix" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d00a78170970967fdb83f9d49b92f959ab2bb829186b113e4f4604ad98e180" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] -name = "unicode-normalization" -version = "0.1.25" +name = "universal-hash" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ - "tinyvec", + "crypto-common 0.2.2", + "ctutils", ] [[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "unit-prefix" -version = "0.5.2" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -2313,9 +3379,12 @@ dependencies = [ [[package]] name = "utf8_iter" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "af3bd9d3e571c26fcce9d033b87ea5ab061b8d2ffe9b7a5675d810d68f03edf0" +dependencies = [ + "utf_types", +] [[package]] name = "utf8parse" @@ -2323,11 +3392,54 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "utf_types" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3b425286980a367278453f3b6d28cdcb134b574e5a35824a6ff5eebad50bb6" + [[package]] name = "uuid" -version = "1.23.2" +version = "1.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514" + +[[package]] +name = "vergen" +version = "10.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7081a999aada4e01c8ee04d32254e021e317dd051a250169305fbf2acf21824" +dependencies = [ + "anyhow", + "bon", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "10.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "55d813ef078c9e739ebe9a121b8319964e1a03cc9e3d2fe30c6cf812d4c57289" +dependencies = [ + "anyhow", + "bon", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "10.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1343066736be577e40cf72914ecd68b369f7033ce0f7db6b25a6d6f7fbb3ed70" +dependencies = [ + "anyhow", + "bon", + "rustversion", +] [[package]] name = "version_check" @@ -2360,23 +3472,13 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "a0181c14ddd6c7b8b0b0132a5f1ea2f32be0d893cd3ea97b6e3b28886b8a3d1c" dependencies = [ "cfg-if", - "once_cell", "rustversion", "wasm-bindgen-macro", "wasm-bindgen-shared", @@ -2384,9 +3486,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "6e931a02a39abdbf66966fc35902b5ed58344750a70885bed4ebb3d8eaf28ed9" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2394,31 +3496,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "2ca4b54280e455bd831e33a6b8e734baf432fe63fbc35c42ac14ce67a043a53a" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "3b1f9c3798725016c6ee5f2f57869ec0831e8bbc0ab0310a86e787e97f41389e" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-encoder" -version = "0.254.2" +version = "0.261.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebaca0b540bdb15d195ff34fb23074255948708b8916a11a339ba4513dc61906" +checksum = "2608e8bb6d67fd68f5a8d0eb1363d6e7bcbc1f8ded5a0bd3a1e382462b876b22" dependencies = [ "leb128fmt", "wasmparser", @@ -2451,9 +3553,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.254.2" +version = "0.261.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5ff8685b587722894b6f25958fc608d315b93b8d23647bfb567664e7006d757" +checksum = "4f20f20e44f7e8aeb6744823ea9d869ede51e51be4fdaedede2852282e54d2d8" dependencies = [ "bitflags", "hashbrown 0.17.1", @@ -2464,9 +3566,9 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.254.2" +version = "0.261.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b03c8f270f3f384f70f42869b5ff7f6253fe4f0aa8590f7edd332c1943e5f51" +checksum = "86a21c9e3325655ba02de3e645bc8357a8b3651a2e3ada25b6dbc37560deb9b7" dependencies = [ "anyhow", "termcolor", @@ -2475,9 +3577,9 @@ dependencies = [ [[package]] name = "wasmtime" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2afcadb2e7d0417cb8f3f322c66eff49338b288f22290c0ca0bd3e9570732aa" +checksum = "fdfacce893df54d319b29720e79edb001cd1b48faaf78fdb3b9c608eaeeea29f" dependencies = [ "addr2line", "async-trait", @@ -2507,14 +3609,14 @@ dependencies = [ "wasmtime-internal-jit-icache-coherence", "wasmtime-internal-unwinder", "wasmtime-internal-versioned-export-macros", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "wasmtime-environ" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de252f4aedfff6c2054ea5bea2454878a931c56e2553c6356b581e5e30a7e4e" +checksum = "f79df81f2a5d7a1cb8b9eb35b4a2d7a8cb8e948bd3e5a1f79036c0094879275a" dependencies = [ "anyhow", "cpp_demangle", @@ -2531,7 +3633,6 @@ dependencies = [ "semver", "serde", "serde_derive", - "sha2", "smallvec", "target-lexicon", "wasm-encoder", @@ -2543,15 +3644,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ad52499e6246d30bf8bf509506bd637248eee17c8dd623e0c7dbe43e7a1036" +checksum = "33c2836b127721e0abdc3490545cdc6d5269d1050a19a4057909901c16e1b781" [[package]] name = "wasmtime-internal-core" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8838d7debfc98a69342d260a990ea6f64adf498184915fccfdbd6718bb40a9b" +checksum = "e765a08b721bf2b2e5cbd3e9365a71b497d57fc5e8b2cf73ddf12d85d502d7fa" dependencies = [ "hashbrown 0.17.1", "libm", @@ -2560,9 +3661,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-cranelift" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c09af53c545d96227b349d35c70fc78e99816923f41428ffff00974bcd145" +checksum = "25e8f190dd62c021d278ab0bd4afab06426844831d6a35dc369835754ad997d4" dependencies = [ "cranelift-codegen", "cranelift-control", @@ -2586,23 +3687,23 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96dce7a8ea302c0f1eb4154eb1756525c90c595bbabbc590abad64d4c5ff8bbb" +checksum = "6326d47c759c0478489a034f1282a6f516ce97594f9af785539697d03add17ec" dependencies = [ "cc", "libc", "rustix", "wasmtime-environ", "wasmtime-internal-versioned-export-macros", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "wasmtime-internal-jit-debug" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "895f3231b24ce0c12c8a7bb129a9f6ddc6772ec78e59748e53af743dcdd733d1" +checksum = "9b78d046468d9aaf81e97954165369693084f43e313daad47f959b1169d596d3" dependencies = [ "cc", "wasmtime-internal-versioned-export-macros", @@ -2610,20 +3711,20 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b60a0c1f735da6b862679b763f8bab653caa477ccc603a25752488b795fec5" +checksum = "ac3e5f3cb3fdc12489163dc60741696dddb32c9ed0662ff59c8dfb177ffd7a07" dependencies = [ "libc", "wasmtime-internal-core", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "wasmtime-internal-unwinder" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97b2c29c8f458bdf1b948058bfbb8141aad0f7abcf0f7cb3479866f4316bf3c" +checksum = "bbf9357720c1477c43f88dace11923737e8aa87abe5f46f90e23c93a2a0fb3fe" dependencies = [ "cranelift-codegen", "log", @@ -2633,20 +3734,20 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "48.0.8" +version = "50.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32766b38d56927eca9a65858ea8c7b1803424db82562aafd69727aa970057561" +checksum = "ce7c663ad018cc86ce824e21b35b8bed9877ee9ca6af8ef8672e28852450392e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", ] [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "d7d179596ff5ec0f6de4db64d54011bde6289cc49603d3a6e4ce3f329207ab88" dependencies = [ "js-sys", "wasm-bindgen", @@ -2662,21 +3763,52 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -2687,29 +3819,248 @@ dependencies = [ ] [[package]] -name = "wit-bindgen" -version = "0.57.1" +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3b93199df0ab874cdf0c6a94f0a0dc3423fe41f1cafb62b8bd7b1deb277aef" +dependencies = [ + "memchr", +] + +[[package]] +name = "wnaf" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795ca18b3fdb5e62bf982199278341ddcf7ebf7d32e25e212ad05d496e95f6fa" +dependencies = [ + "ff", + "group", + "hybrid-array", + "primefield", +] + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "yasna" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" +dependencies = [ + "bit-vec 0.9.1", + "time", +] + +[[package]] +name = "yoke" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure 0.14.0", +] [[package]] name = "zerocopy" -version = "0.8.49" +version = "0.8.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b" +checksum = "e5fe1f8f1b06191a00962174c61aa5005e0bb391a6d80d07e24d115c01a92ed8" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.49" +version = "0.8.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863ad3ac83293fb4d740aedbfdc9240dd8d1a50c1099acd76ce80ce7c7230c7f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure 0.14.0", +] + +[[package]] +name = "zeroize" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58a2799cfe9a1670c7ea8edbd52ef8edb93cb37a7f83bf31ba9e35d9dae6a40" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e" +checksum = "c3743ddbf47738d929cd1ae2e199d40d0162979dfe31aef8ae646d2bf00bf97a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.9", ] [[package]] @@ -2720,6 +4071,6 @@ checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" [[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/Cargo.toml b/Cargo.toml index 531b95d37..f9206c78c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ members = [ "crates/before/wasm32-pins/guest", "crates/before/wasm32-pins/harness", "crates/before/wasm32-pins/protocol", + "crates/rumors-budget-curves", + "crates/rumors-netperf", "crates/rumors-tracing", "crates/rumors-testkit", "crates/suanpan", @@ -49,10 +51,17 @@ default-members = [ [workspace.dependencies] alloc-meter = { path = "crates/alloc-meter" } +aes-gcm = { version = "0.11", default-features = false } +anyhow = "1" async-stream = "0.3" -base64 = "0.22" +# The visualizer encodes through the scalar URL-safe engine alone, so the +# SIMD engines behind the default `simd-unsafe` feature stay uncompiled. +base64 = { version = "0.23", default-features = false, features = ["std"] } before = { path = "crates/before" } +# A fixed-size bit array backs `ByteSet`, the protocol's set of radixes. +bitvec = { version = "1.1", default-features = false } board-fuel-harness = { path = "crates/before/board-fuel/harness" } +sha2 = "0.11" sha3 = "0.12" borsh = "1" bytes = "1" @@ -66,31 +75,52 @@ cbor-diag = { git = "https://github.com/oxidecomputer/cbor-diag-rs", rev = "a6a7 ciborium = "=0.2.2" clap = "4" console_error_panic_hook = "0.1" -criterion = "0.5" +criterion = "0.8" +csv = "1" +dirs = "7" dlmalloc = "0.2" dsi-bitstream = { version = "0.10.1", default-features = false, features = ["alloc"] } flate2 = "1" focused-fuel-protocol = { path = "crates/before/focused-fuel/protocol" } +# 0.11.0 does not build on illumos: it combines `libc`'s `POSIX_SPAWN_*` +# flags, `i16` there, into a `c_int`. +fork = "0.10" futures = { version = "0.3", default-features = false, features = ["std", "async-await"] } fuzzfit-harness = { path = "crates/before/fuzzfit/harness" } hex = "0.4" +hkdf = "0.13" +hmac = "0.13" +# HPKE (RFC 9180), rozbb/rust-hpke on RustCrypto's `p256`, `hkdf` and +# `aes-gcm`: the bootstrap's sealed exchange. +hpke = { version = "0.15", default-features = false } indicatif = "0.18" -insta = "1.47" -itertools = "0.14" +insta = "1.49" +itertools = "0.15" libm = "0.2" mimalloc = "0.1" -num-bigint = "0.4" +nix = { version = "0.31", default-features = false } +num-bigint = "0.5" num-traits = "0.2" peak_alloc = "0.3" plotters = { version = "0.3", default-features = false } +# 1.0's `block_on` keeps a wakeup only in its thread's park token, so a +# future that parks its own thread while polled (`std::thread::scope` does, +# to wait for its threads) can consume the wakeup and leave `block_on` +# parked for good; the peer suite's redaction race does this. 0.4 keeps the +# wakeup in its own state. pollster = { version = "0.4", features = ["macro"] } postcard = { version = "1", default-features = false, features = ["use-std"] } -proptest = "1" -rand = "0.9" +proptest = "1.12" +rand = "0.10" rand08 = { package = "rand", version = "0.8" } -rand_chacha = "0.9" +rand_chacha = "0.10" rand_chacha03 = { package = "rand_chacha", version = "0.3" } +rand_distr = "0.6" rayon = "1" +# A self-signed certificate for the TLS sessions of the TLS record suite +# and the link-measurement tool, generated per run, so no key is ever +# committed. +rcgen = { version = "0.14", default-features = false, features = ["crypto", "ring"] } rumors = { path = "." } rumors-testkit = { path = "crates/rumors-testkit" } rustc_version = "0.4" @@ -99,26 +129,36 @@ rustc_version = "0.4" # and surfacecheck refuses any document whose format_version differs from # `rustdoc_types::FORMAT_VERSION`. rustdoc-types = "=0.59.0" +# TLS for the TLS record suite and the link-measurement tool, on the +# `ring` provider, which builds with a C compiler alone on every host they +# run on. +rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] } schnellru = { version = "0.2.4", default-features = false } seq-macro = "0.3" serde = { version = "1", default-features = false } serde_bytes = "0.11" serde_json = "1" serde_test = "1" -smallvec = { version = "1.15", features = ["union"] } +smallvec = { version = "1.16", features = ["union"] } spin = { version = "0.12", default-features = false, features = ["spin_mutex"] } static_assertions = "1.1" strum_macros = "0.28.0" suanpan = { path = "crates/suanpan" } suanpan-fuel-protocol = { path = "crates/suanpan/fuel/protocol" } -tempfile = "=3.23.0" +tempfile = "3.27" thiserror = "2" -tinyvec = { version = "1.11", features = ["alloc"] } +tinyvec = { version = "1.13", features = ["alloc"] } tokio = { version = "1", default-features = false } +tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] } +toml = "1" tracing = "0.1" +# The link-measurement tool's readable source revision, from the git +# command line, which every host that builds from a checkout already has. +vergen-gitcl = "10" wasm-bindgen = "0.2" wasm32-pins-protocol = { path = "crates/before/wasm32-pins/protocol" } -wasmtime = { version = "48.0.8", default-features = false } +wasmtime = { version = "50.0.1", default-features = false } +zeroize = "1.9" [package] name = "rumors" @@ -147,17 +187,33 @@ bench = false # Test-only introspection and deterministic scheduling infrastructure. # Enabled for this crate's own tests via the self-referential dev-dependency # below; never enable it in an application. -test-internals = ["tokio/rt", "dep:cbor-diag"] -# Conformance suites for caller-built links and bookmark storage. -# Enable from a dev-dependency to validate an application's adapters. +test-internals = ["tokio/rt", "dep:cbor-diag", "dep:proptest", "dep:rand_chacha"] +# A conformance suite for caller-built bookmark storage. Enable from a +# dev-dependency to validate an application's storage adapter. conformance = [] # Atomic file storage for bookmarks, driven by caller-supplied blocking execution. fs = ["dep:tempfile"] [dependencies] before = { workspace = true, features = ["serde"] } +bitvec.workspace = true bytes.workspace = true +# The `zeroize` features clear the network secret's HMAC key state, and +# the SHA-256 cores inside it, when a path key drops. +sha2 = { workspace = true, features = ["zeroize"] } +hmac = { workspace = true, features = ["zeroize"] } sha3.workspace = true +zeroize.workspace = true +# The bootstrap's sealed secret: HPKE base mode with DHKEM(P-256, +# HKDF-SHA256), HKDF-SHA256 and AES-256-GCM, drawing its keys from the +# operating system. +hpke = { workspace = true, features = ["nistp", "aes", "getrandom"] } +# Not used directly: `hpke` builds `aes-gcm` without its `zeroize` feature, +# and enabling it here makes the AES key schedule inside each HPKE +# context clear when the context drops. +aes-gcm = { workspace = true, features = ["zeroize"] } +# The network secret's key schedule (`NetworkKeys`). +hkdf.workspace = true itertools.workspace = true serde = { workspace = true, default-features = true, features = ["derive"] } ciborium.workspace = true @@ -175,6 +231,12 @@ tempfile = { workspace = true, optional = true } # The wire-capture renderer behind `test-internals` renders every captured # item in diagnostic notation through this crate. cbor-diag = { workspace = true, optional = true } +# The property-test support behind `test-internals` (`testing::property`) +# draws each test network's seed as a proptest input and derives the +# network's secret from a ChaCha stream, whose output for a seed is fixed +# across platforms and Rand versions. +proptest = { workspace = true, optional = true } +rand_chacha = { workspace = true, optional = true } [dev-dependencies] rumors = { workspace = true, features = ["test-internals", "conformance"] } @@ -206,6 +268,17 @@ rand_chacha.workspace = true pollster.workspace = true # The allocation-pricing suites read per-thread allocator traffic from it. alloc-meter.workspace = true +# The seed-after-fork regression test forks its process, through a crate +# rather than `unsafe` calls of its own. +fork.workspace = true +# The sealed exchange's tests seal and open through `hpke` directly, as an +# oracle for the documented bindings, with its allocating API. +hpke = { workspace = true, features = ["alloc"] } +# The TLS record suite runs sessions over TLS 1.3 to check that the +# default write batch fits each record in one TCP segment. +rcgen.workspace = true +rustls.workspace = true +tokio-rustls.workspace = true [profile.dev] debug = "line-tables-only" @@ -221,6 +294,39 @@ opt-level = 2 [profile.dev.package.suanpan] opt-level = 2 +# The session-budget suite's 100,000-message sessions spend about half their +# time in this crate's own code, which runs several times slower +# unoptimized: optimizing it takes each of those tests from about 120 s to +# about 41 s, against the gate's 300 s per-test limit. The cost is compile +# time: the crate's unit-test binary compiles in about 300 s from cold +# rather than 117 s. `debug-assertions` and overflow checks stay on, as for +# `before` and `suanpan`. The session futures' sizes, which +# `tests/future_size.rs` and the gossip session-size test check, are the +# same at opt-level 0 and 1. +[profile.dev.package.rumors] +opt-level = 1 + +# The session-budget suite classifies tens of millions of traced allocator +# events in the meter's lifetime analysis, which dominates its execution +# unoptimized. +[profile.dev.package.alloc-meter] +opt-level = 2 + +# Leaf paths and node hashes are SHA-256, which every test that builds a +# tree computes many times; bookmark checksums and the test fixtures' +# fingerprints are SHA3-256. On x86_64, keccak computes SHA3 in software, +# and unoptimized that costs about 54 µs a hash. Optimizing the hash crates +# keeps hashing at release speed in the test suite without touching +# release. +[profile.dev.package.sha2] +opt-level = 3 + +[profile.dev.package.keccak] +opt-level = 3 + +[profile.dev.package.sha3] +opt-level = 3 + # The fuel guests' profile (the fuzz-fit guest's and the fuel board's), part # of what fuel measures: fuel counts the instructions of this codegen. One # codegen unit keeps function layout independent of build parallelism, and it @@ -242,6 +348,16 @@ panic = "abort" inherits = "release" overflow-checks = false +# The release-profile test run's profile: `release` codegen, so properties +# run at CI's case count in reasonable time, with the runtime checks the dev +# profile grants. Overflow traps and `debug_assert!`s then run in every +# release-profile test run, not only in the gate's dev-profile `test-all`, +# so arithmetic that wraps silently in release fails a test instead. +[profile.release-checked] +inherits = "release" +overflow-checks = true +debug-assertions = true + # Profiling the benches needs symbolicated stacks; line tables are enough # for samply/Instruments without the compile-time cost of full debug info. [profile.bench] @@ -262,7 +378,3 @@ harness = false [[bench]] name = "gossip_fixed" harness = false - -[[bench]] -name = "window_wallclock" -harness = false diff --git a/README.md b/README.md index c09346350..95b95cfc1 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,8 @@ constraint. A non-conforming peer can leave synchronization waiting indefinitely. Applications choose deadlines when they need to bound those waits. Authenticating peers and securing the transport are the application's job; - the `link` module lists exactly what the protocol asks of the transport. + [what securing the transport means](#what-securing-the-transport-means) + lists exactly what the protocol asks of it. - **If bandwidth is your scarce resource.** `rumors` buys low latency with bandwidth. Small reconciliations can spend several kilobytes of protocol traffic per message. Metered, narrow, or high-loss links may call for a @@ -103,18 +104,22 @@ async fn main() -> Result<(), Box> { // A send commits right here. alice.send("the meeting is at noon".to_string())?; - // A session runs over a `Link`: a control byte stream plus a supply - // of independent data streams (see the `link` module); here, the - // in-memory pair. Alice serves one gossip session... - let (mut near, mut far) = rumors::link::memory(); + // A session runs over one connection, taken as its two halves (see + // Transport below); here, an in-memory pair. Alice serves one gossip + // session... + let (near, far) = tokio::io::duplex(64 * 1024); let serve = alice.clone(); tokio::spawn(async move { - serve.gossip_once(&mut far).await.unwrap(); + let (read, write) = tokio::io::split(far); + let read = tokio::io::BufReader::new(read); + serve.gossip_once(read, write).await.unwrap(); }); // ...and Bob joins the universe through it, arriving as a full replica. - let rumors::Joined::Joined { peer: bob } = - Peer::::bootstrap().join(&mut near).await + let (read, write) = tokio::io::split(near); + let read = tokio::io::BufReader::new(read); + let rumors::Joined::Joined { peer: bob, .. } = + Peer::::bootstrap().join(read, write).await else { panic!("Alice must serve the bootstrap"); }; @@ -166,26 +171,154 @@ protocol message of a live session, as raw CBOR items, for debuggers, recorders, and tracing adapters — attach a handler from the `observe` module (`Peer::observe`). -## Transport: bring a `Link` - -A session's transport is a `Link`: one persistent bidirectional -*control stream* plus a supply of independent, individually -flow-controlled unidirectional *data streams*, opened lazily as -reconciliation needs them. The `link` module states what an -implementation must guarantee, ships the in-memory instantiation -(`link::memory`), and documents how to bind a real transport (QUIC -connections map streams one to one; TCP can carry one stream per -connection behind a routing listener). A conformance suite (the -`conformance::link` module, unlocked by the `conformance` cargo feature) -checks those guarantees on a caller-built link. `Link`'s docs state -what a session promises on `Ok`, `Err`, -and cancellation. +## Transport + +A session runs over one connection to its peer, which it takes as two +halves: a buffered read half implementing +[`AsyncBufRead`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncBufRead.html) +and a write half implementing +[`AsyncWrite`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html). +Every session method takes the halves by value. The single-session +methods (`Rumors::gossip_once`, `Bootstrap::join`, and +`Peer::retire`) return them when the session completes; the +`Rumors::gossip` driver owns them for its whole lifetime and drops them +when it ends. Tokio implements both traits for mutable references, so +pass `&mut read, &mut write` to keep halves you hold elsewhere, such as a +connection you mean to reuse after a driver ends. + +The connection must be: + +- **one reliable, ordered duplex byte stream**: every byte written + arrives, once, in the order written; +- **independent in its two directions**: a read proceeds while the same + side's write is blocked, so a carrier that couples them (a half-duplex + turn protocol, or a lock held across a read and a write) can deadlock a + session; +- **paced by its receiver**: a writer that runs ahead of its reader + waits, and any positive buffer capacity suffices; sessions stay live + down to a one-byte buffer; +- **closed visibly**: when the peer departs, the read half reports end of + stream or an error, and every write, pending or later, eventually + completes or fails. + +A TCP connection split with `TcpStream::into_split` meets every clause, +as does one bidirectional QUIC stream, or a `tokio::io::duplex` pair for +an in-process peer. The crate opens no connections itself. + +Wrap the read half in `tokio::io::BufReader`: a TCP read half, a TLS +stream's read half, and a duplex pipe implement only `AsyncRead`. A +session reads its items from the buffer and consumes exactly the bytes +that are its own, so whatever follows a session stays in your buffer: +keep the `BufReader` for the next session on the same connection, and +never read the connection around it. The write half needs no wrapper: a +session gathers the messages it writes into *batches*, in a buffer of +its own of about 63 KiB, and writes and flushes each batch at once, so +each batch reaches the write half as one write: one system call on a TCP +socket. A batch ends when the session has nothing more ready to send, or +when it reaches the bounds `Peer::write_batch_range` sets. The default +bounds suit TLS 1.3 over TCP: a batch of small messages leaves as one +record that fills at most one TCP segment, and any other batch as one +record of at most TLS's largest plaintext, unless one message alone +outgrows that record and goes out by itself (`default::tls`). A session +writes a message at least the buffer's size directly, and continues any +write the transport takes only part of. A `BufWriter` around the write +half is safe, but only copies again what the session has already +gathered. + +Over TCP, disable Nagle's algorithm on both ends with +`TcpStream::set_nodelay(true)` before splitting the stream. A session +often writes a short message and then waits for the peer's answer to it. +With Nagle's algorithm on, the kernel holds a short write back until the +peer acknowledges the bytes already in flight, and the peer's TCP stack +may delay that acknowledgement, commonly by tens to hundreds of +milliseconds, because it has nothing of its own to send yet. Each such +exchange can then stall for the delayed-acknowledgement interval, and a +session makes many in sequence as it descends the tree. + +A departed peer that never closes the connection leaves a session +waiting, and so does a transport whose writes never complete; configure +`Peer::session_deadline` to bound such waits. + +### What a session promises + +Sessions synchronize message sets and may also join or retire a peer. +Their outcomes determine whether the replica and the connection can be +reused: + +- **Success:** both sides confirmed completion. The returned halves rest + exactly at the session boundary, ready for another session. Gossip + returns `Gossiped`; bootstrap and retirement report their results + through `Joined` and `Retire`, which return the halves in a + `Connection::Reusable` once this side has joined or left the network. +- **Failure:** the connection's position is unknown: discard it and + reconnect. A later session on it gets no typed warning; it can fail in + any way, or misread the stale bytes. Failure does not always mean that + nothing changed: a failure in + `Phase::Completion` can follow a + local commit. Accepting a retirement can also commit content before a + bookmark write fails; see `Error::Bookmark`. A bootstrap or + retirement that fails after this side has joined or left the network + reports the failure as a `Connection::Lost` in that outcome. +- **Cancellation:** dropping an active session future also leaves the + connection at an unknown position; discard it. No partial + reconciliation is published, but a completed local commit is not + undone. Cancelling bootstrap or retirement also drops the builder or + peer it consumed; no outcome is returned for retry. See `Bookmark` + for the effects on restart bookkeeping. + +A bootstrap whose session fails after its whole identity arrived keeps +its live peer, beside a `Connection::Lost`. Bootstrap attaches a +selected bookmark once its wire session has ended with this side holding +its identity, whether or not the session completed. Failing or +cancelling that attachment leaves the connection where the session left +it; `Joined::Unbookmarked` preserves the joined peer after an +attachment failure. + +Configure `Peer::session_deadline` to bound gossip, bootstrap, and +retirement exchanges while leaving idle waits untimed. Post-join bookmark +attachment is outside this deadline. Discard the connection on expiry. +`Gossip::Unconditionally` can initiate liveness probes on an otherwise +idle connection. + +### What securing the transport means + +The application authenticates peers and secures the transport. Protocol +checks help diagnose incompatible or buggy peers; they do not make a +completed session's updates trustworthy. An authorized peer can follow +the protocol while arbitrarily changing the gossip set. A non-conforming +peer can leave synchronization waiting indefinitely, so applications +choose deadlines when they need to bound those waits. + +The transport has these responsibilities: + +- **Authentication is authorization.** Any counterparty that can + complete a session holds full write authority over the set; the + protocol makes no finer-grained access decision. +- **Integrity.** The wire decoders detect malformed frames, not + tampering: a transport that lets a third party modify bytes in flight + has granted that party the session. In a bootstrap it has also granted + the network's secret: the third party can replace the joining peer's + public key with its own and open the secret the provider seals to it. + A leaked secret stays useful for the network's whole life, since it + cannot be rotated (see + keyed addresses). +- **Confidentiality.** Session traffic (message bodies, set sizes, + version structure, the greeting's metadata) crosses the connection in + cleartext; the protocol adds no encryption of its own. The one exception + is the network's secret, which a provider seals with HPKE for the + joining peer it serves. The set's integrity + does not rest on confidentiality: the digests and address bytes an + observer reads on the wire do not let it compute those of versions it + chooses (see keyed addresses). +- **Freshness.** The protocol does not authenticate a connection or a + session as new; a transport that could replay recorded traffic into a + live connection must rule that out itself. ## Runtime independence Sessions and observers are plain futures and streams, driven entirely by the caller. The I/O traits are Tokio's runtime-independent -[`AsyncRead`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncRead.html) +[`AsyncBufRead`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncBufRead.html) and [`AsyncWrite`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html); no Tokio runtime, spawning, sockets, or timers are required by this crate. @@ -214,7 +347,7 @@ Each bound guards replication: most `Peer::payload_depth_limit` steps (256 by default, ample for ordinary types); an over-deep value is rejected at send. The limit is held to exact equality fleet-wide at every handshake, so - an admitted payload is transferable everywhere; the knob's docs + an admitted payload is transferable everywhere; the setting's docs carry the full contract. On compatibility across versions of your own type: because CBOR @@ -229,8 +362,8 @@ if it starts out only having one variant, `V1`. Every feature is off by default. -- `conformance`: the public validation suite for caller-built `link` - instantiations (the `conformance::link` module). Enable it from a +- `conformance`: the public validation suite for caller-built bookmark + storage (the `conformance::bookmark` module). Enable it from a dev-dependency; it is safe, though pointless, in an application. - `fs`: `FileBookmark` and its caller-driven blocking-I/O bridge. - `test-internals`: this crate's own test scaffolding, enabled through diff --git a/benches/branch_hash.rs b/benches/branch_hash.rs index 33cc2182d..6789c2ff0 100644 --- a/benches/branch_hash.rs +++ b/benches/branch_hash.rs @@ -1,32 +1,43 @@ // `criterion_group!` generates a public registrar with no documentation. #![allow(missing_docs)] -//! Feeding-strategy microbenchmark behind `Hash::branch`'s one-shot form. +//! Feeding-strategy microbenchmark behind `HashKey::branch`'s one-shot form. //! -//! A branch preimage is `kind ‖ prefix_len ‖ prefix ‖ count ‖ (radix ‖ hash)*` -//! — dominated by fixed-width child records, several to one of SHA3-256's -//! 136-byte rate blocks. The shipped `Hash::branch` assembles the whole +//! A branch preimage is `kind ‖ height ‖ prefix_len ‖ prefix ‖ count ‖ +//! (radix ‖ hash)*`, hashed by HMAC-SHA-256 under the tree hash key — +//! dominated by fixed-width child records, several to one of SHA-256's +//! 64-byte blocks. The shipped `HashKey::branch` assembles the whole //! preimage in a contiguous buffer and hashes it in one shot; the -//! alternative feeds the sponge one `update` per field. This bench measures -//! exactly that comparison over the current preimage layout, across fan-outs -//! from the smallest representable branch to the saturated 256, so the -//! claim at `Hash::branch` stays re-measurable: run +//! alternative feeds the keyed hasher one `update` per field. This bench +//! measures exactly that comparison over the current preimage layout, across +//! fan-outs from the smallest representable branch to the saturated 256, so +//! the claim at `HashKey::branch` stays re-measurable: run //! `just bench branch_hash` and compare the `contiguous` and `streamed` //! curves. //! //! The contiguous series calls the production implementation through its //! test-only entry point. The streamed alternative spells out the same input, -//! and an untimed assertion keeps the two forms equivalent. +//! and an untimed assertion keeps the two forms equivalent. Both key the hash +//! once, outside the timed loop, and clone the keyed state per branch, as +//! the tree does. use std::hint::black_box; use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; -use rumors::testing::MERKLE_HASH_LEN; -use sha3::{Digest, Sha3_256}; +use hmac::{Hmac, KeyInit, Mac}; +use rumors::testing::{BranchHasher, HASH_KEY_LEN, MERKLE_HASH_LEN}; +use sha2::Sha256; /// Kind byte leading a branch preimage, mirrored from the documented layout. const BRANCH_TAG: u8 = 1; +/// The height the benched branch sits at: one below the root, as a hot +/// interior branch near the root does. +const HEIGHT: u8 = 31; + +/// A fixed raw key: only that both series use the same one matters. +const KEY: [u8; HASH_KEY_LEN] = [0x5e; HASH_KEY_LEN]; + /// A hot node's compressed span: short, as path compression typically leaves /// interior branches near the root. const PREFIX: &[u8] = &[0xa5, 0x5a, 0x3c]; @@ -50,43 +61,54 @@ fn children(k: usize) -> Vec<(u8, [u8; MERKLE_HASH_LEN])> { } /// Hash a branch with the production contiguous preimage builder. -fn contiguous(prefix: &[u8], children: &[(u8, [u8; MERKLE_HASH_LEN])]) -> [u8; MERKLE_HASH_LEN] { - rumors::testing::branch_hash(prefix, children.iter().copied()) +fn contiguous( + key: &BranchHasher, + prefix: &[u8], + children: &[(u8, [u8; MERKLE_HASH_LEN])], +) -> [u8; MERKLE_HASH_LEN] { + key.branch_hash(usize::from(HEIGHT), prefix, children.iter().copied()) } -/// The streamed form: one `update` call per field, so the sponge sees the -/// preimage in radix-byte and hash-width fragments. -fn streamed(prefix: &[u8], children: &[(u8, [u8; MERKLE_HASH_LEN])]) -> [u8; MERKLE_HASH_LEN] { - let mut hasher = Sha3_256::new(); - hasher.update([BRANCH_TAG]); - hasher.update([u8::try_from(prefix.len()).expect("a compressed span fits in one length byte")]); +/// The streamed form: one `update` call per field, so the keyed hasher sees +/// the preimage in radix-byte and hash-width fragments. +fn streamed( + key: &Hmac, + prefix: &[u8], + children: &[(u8, [u8; MERKLE_HASH_LEN])], +) -> [u8; MERKLE_HASH_LEN] { + let mut hasher = key.clone(); + hasher.update(&[BRANCH_TAG, HEIGHT]); + hasher + .update(&[u8::try_from(prefix.len()).expect("a compressed span fits in one length byte")]); hasher.update(prefix); let count = u16::try_from(children.len()).expect("fan-out fits u16"); - hasher.update(count.to_be_bytes()); + hasher.update(&count.to_be_bytes()); for (radix, hash) in children { - hasher.update([*radix]); + hasher.update(&[*radix]); hasher.update(hash); } - hasher.finalize()[..MERKLE_HASH_LEN] + hasher.finalize().into_bytes()[..MERKLE_HASH_LEN] .try_into() .expect("digest prefix has the comparison width") } -/// Compare the production contiguous hash with incremental sponge updates. +/// Compare the production contiguous hash with incremental hasher updates. fn branch_hash(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("branch_hash"); + let production = BranchHasher::new(&KEY); + let keyed = >::new_from_slice(&KEY).expect("HMAC accepts a key of any length"); for &fanout in FANOUTS { let kids = children(fanout); assert_eq!( - contiguous(PREFIX, &kids), - streamed(PREFIX, &kids), + contiguous(&production, PREFIX, &kids), + streamed(&keyed, PREFIX, &kids), "feeding strategies must hash the same branch input", ); group.bench_with_input(BenchmarkId::new("contiguous", fanout), &kids, |b, kids| { - b.iter(|| contiguous(black_box(PREFIX), black_box(kids))); + b.iter(|| contiguous(&production, black_box(PREFIX), black_box(kids))); }); group.bench_with_input(BenchmarkId::new("streamed", fanout), &kids, |b, kids| { - b.iter(|| streamed(black_box(PREFIX), black_box(kids))); + b.iter(|| streamed(&keyed, black_box(PREFIX), black_box(kids))); }); } group.finish(); diff --git a/benches/gossip_fixed.rs b/benches/gossip_fixed.rs index addc54616..a762899af 100644 --- a/benches/gossip_fixed.rs +++ b/benches/gossip_fixed.rs @@ -6,7 +6,7 @@ //! Every fixture starts with a total universe size of `N = 10_000` possible //! actions and varies only where the work lands: shared pre-fork insertions, //! post-fork divergent insertions, or post-fork redactions. Each benchmark -//! drives [`Rumors::gossip`] over one persistent in-memory link, so the timed +//! drives [`Rumors::gossip`] over one persistent in-memory connection, so the timed //! body pays for the gossip session rather than transport allocation. //! //! The fixed-size groups measure the wire protocol on the same fixtures. Their @@ -17,7 +17,7 @@ //! - `gossip_fixed_unilateral_insertions`: one-side post-fork insertions `I`. //! - `gossip_fixed_unilateral_redactions`: one-side post-fork redactions `R`. //! -//! # The latency knob +//! # The latency sweep //! //! Two further groups reuse the bidirectional fixtures but add a third //! dimension: one-way link latency, swept as the x-axis at a few fixed @@ -27,7 +27,7 @@ //! - `gossip_latency_bidir_insertions`: `I ∈ {0, 5000}`. //! - `gossip_latency_bidir_redactions`: `R = 2500`. //! -//! Sessions run over the test kit's delayed-pipe link, which +//! Sessions run over the test kit's delayed-pipe connection, which //! charges wire delay to a paused runtime clock, so the sweep costs //! wall-clock compute only and the reported duration is elapsed compute time //! plus virtual wire stall. Read each line's intercept as the protocol's @@ -37,16 +37,16 @@ //! changed" handshake a production peer pays every gossip round. //! //! Read the slopes for regressions: a hop count scaling with disputed -//! scopes rather than tree depth is the serialized inter-stage regime the -//! session window exists to prevent, and it shows up here as slope growing -//! with divergence. +//! scopes rather than tree depth is the serialized regime the memory +//! budget exists to avoid, and it shows up here as slope growing with +//! divergence. use std::hint::black_box; use std::time::Duration; use criterion::{BatchSize, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; use rand::seq::SliceRandom; -use rand::{RngCore, SeedableRng}; +use rand::{Rng, SeedableRng}; use rand_chacha::ChaChaRng; use rumors::{Peer, Rumors, Version}; use rumors_testkit::bench::{grid, latency}; @@ -76,12 +76,12 @@ const LATENCY_INSERTIONS: &[usize] = &[0, 5_000]; /// sweep already carries the size-scaling signal. const LATENCY_REDACTIONS: &[usize] = &[2_500]; -/// Per-stream in-flight window for the latency sweep: far above any -/// session's per-stream transfer at `N = 10_000`. +/// Per-direction in-flight window for the latency sweep: far above any +/// session's one-direction transfer at `N = 10_000`. /// /// Measurements therefore isolate round-trip serialization from -/// bandwidth-delay throttling (the window caps per-stream throughput at -/// `capacity / delay`). +/// bandwidth-delay throttling (the pipe's in-flight capacity caps each +/// direction's throughput at `capacity / delay`). const LATENCY_CAPACITY: usize = 8 * 1024 * 1024; /// How the two peers diverge after their shared history. @@ -288,8 +288,8 @@ fn build_unilateral_redactions(total_redactions: usize) -> (Rumors, Rumors Rumors { // Fixed, so every run benchmarks the same network. let mut rng = ChaChaRng::seed_from_u64(0xe9f4_fc18_d119_7299); diff --git a/benches/gossip_grid.rs b/benches/gossip_grid.rs index 916c977ab..d6dac5446 100644 --- a/benches/gossip_grid.rs +++ b/benches/gossip_grid.rs @@ -17,8 +17,8 @@ //! A naive harness would allocate a fresh transport per Criterion iteration. //! The //! gossip exchange chain is statically bounded and self-delimiting (it closes -//! on its own counter, never on EOF), so a completed session leaves the link -//! at its next boundary. [`Wire::new`] therefore allocates once for all cells. +//! on its own counter, never on EOF), so a completed session leaves the +//! connection at its next boundary. [`Wire::new`] therefore allocates once for all cells. use std::hint::black_box; diff --git a/benches/window_wallclock.rs b/benches/window_wallclock.rs deleted file mode 100644 index 417ce9f74..000000000 --- a/benches/window_wallclock.rs +++ /dev/null @@ -1,98 +0,0 @@ -// `criterion_group!` generates a public registrar with no documentation. -#![allow(missing_docs)] - -//! Wall-clock cross-check of the window suites' virtual-time model. -//! -//! Runs a small budget × divergence grid over the same delayed pipes as the -//! window knee and operator suites, but on a running clock, so pipe delays burn -//! real time under real timer scheduling. The virtual model predicts each -//! cell's time as `hops × delay` plus compute; criterion's mean for a cell -//! should land within a few percent of the virtual figure for the same shape. -//! Compare by eye after `just bench window_wallclock`; the grid is small -//! because every wave here costs real milliseconds. - -use std::time::Duration; - -use criterion::{Criterion, criterion_group, criterion_main}; -use rand::{RngCore, SeedableRng}; -use rand_chacha::ChaChaRng; -use rumors::{Peer, Rumors}; -use rumors_testkit::bench::latency; - -/// One-way delay: small, so a serialized cell still finishes in tens of -/// milliseconds of real time. -const DELAY: Duration = Duration::from_millis(2); - -/// Per-stream pipe buffering: roomy, matching the generator's -/// latency-only regime. -const LINK_CAPACITY: usize = 8 * 1024 * 1024; - -/// Messages both peers share before the fork. -const COMMON: usize = 2_048; - -/// The grid: three cells over two budgets. -/// -/// The tight budget runs below and above its serialization knee (1k -/// pipelined, 10k serialized); the roomy budget runs the same large -/// divergence as the pipelined contrast at identical work. -const CELLS: &[(&str, usize, usize)] = &[ - ("256KiB-1k", 256 << 10, 1_000), - ("256KiB-10k", 256 << 10, 10_000), - ("16MiB-10k", 16 << 20, 10_000), -]; - -/// Compare selected window configurations against real timer scheduling. -fn window_wallclock(criterion: &mut Criterion) { - let mut group = criterion.benchmark_group("window_wallclock"); - group.sample_size(10); - for &(name, budget, divergence) in CELLS { - let mut wire = latency::DelayedWire::new_wall_clock(LINK_CAPACITY, DELAY); - group.bench_function(name, |bencher| { - bencher.iter_batched( - || diverged(budget, divergence), - |(left, right)| wire.round_trip(left, right), - criterion::BatchSize::PerIteration, - ); - }); - } - group.finish(); -} - -/// Two peers with a shared prefix, diverged by `divergent` messages each. -fn diverged(budget: usize, divergent: usize) -> (Rumors, Rumors) { - // Fixed, so every run benchmarks the same corpus. - let mut rng = ChaChaRng::seed_from_u64(0x0b05_2026_0d0c_0002); - let left = Peer::seed_rng(&mut rng) - .sync_memory_budget(budget) - .into_rumors(); - send_random(&left, COMMON, &mut rng); - - let right = pollster::block_on(async { - let (mut provider, mut newcomer) = rumors::link::memory_with_capacity(LINK_CAPACITY); - let (served, joined) = tokio::join!( - left.gossip_once(&mut provider), - Peer::::bootstrap().join(&mut newcomer), - ); - served.expect("serve bootstrap"); - (match joined { - rumors::Joined::Joined { peer } => peer, - _ => panic!("provider is established"), - }) - .sync_memory_budget(budget) - .into_rumors() - }); - - send_random(&left, divergent, &mut rng); - send_random(&right, divergent, &mut rng); - (left, right) -} - -/// Commit `n` random payloads as one batch. -fn send_random(rumors: &Rumors, n: usize, rng: &mut ChaChaRng) { - rumors - .send_all((0..n).map(|_| rng.next_u64())) - .expect("flat test payloads are within any depth limit"); -} - -criterion_group!(benches, window_wallclock); -criterion_main!(benches); diff --git a/clippy.toml b/clippy.toml index 0e6b4eeee..177e98212 100644 --- a/clippy.toml +++ b/clippy.toml @@ -13,7 +13,39 @@ disallowed-macros = [ { path = "proptest::prop_assume", reason = "rejected cases count toward a run-wide limit, so some case count fails; construct inputs that satisfy the precondition" }, ] +# Tokio's `mpsc` channels are disallowed. The protocol's channels use the +# crate's own wrapper over `futures-channel` +# (`src/tree/mirror/streaming/channel.rs`), and other code uses that wrapper +# or `futures-channel` directly. +# +# Tokio's `mpsc` keeps its shared state cache-padded: two of its fields are +# aligned to 128 bytes on x86-64, AArch64, and powerpc64, and to between 32 +# and 256 bytes elsewhere, so each channel is an over-aligned allocation. The +# system allocator serves those through its aligned-allocation entry point, +# which is slow on some allocators, illumos's libumem (Rust's default +# allocator there) among them. A session creates its protocol channels anew, +# so the cost would recur on every sync. +# +# Tokio's `broadcast`, `watch`, and `oneshot` stay allowed: none of them is +# over-aligned, and `watch` serves as the replica's state cell, created once +# per peer rather than per session. +# +# The types catch every written mention, imports included; the constructors +# catch a channel whose halves are never named. +disallowed-types = [ + { path = "tokio::sync::mpsc::Sender", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::Receiver", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::WeakSender", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::UnboundedSender", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::UnboundedReceiver", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::WeakUnboundedSender", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::Permit", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::OwnedPermit", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, +] + disallowed-methods = [ + { path = "tokio::sync::mpsc::channel", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, + { path = "tokio::sync::mpsc::unbounded_channel", reason = "Tokio's `mpsc` keeps its shared state cache-padded, so every channel is an over-aligned allocation, slow on some allocators (illumos's libumem among them); use the crate's streaming channel or futures-channel" }, { path = "proptest::strategy::Strategy::prop_filter", reason = "rejected draws count toward a run-wide limit, so some case count fails; construct values that satisfy the predicate" }, { path = "proptest::strategy::Strategy::prop_filter_map", reason = "rejected draws count toward a run-wide limit, so some case count fails; construct values that satisfy the predicate" }, { path = "proptest::strategy::statics::Filter::new", reason = "rejected draws count toward a run-wide limit, so some case count fails; construct values that satisfy the predicate" }, diff --git a/crates/alloc-meter/src/lib.rs b/crates/alloc-meter/src/lib.rs index 939118f81..e3f09d4c5 100644 --- a/crates/alloc-meter/src/lib.rs +++ b/crates/alloc-meter/src/lib.rs @@ -20,6 +20,12 @@ //! A harness that accepts plain function pointers rather than a closure reads //! the same ledger through [`reset`] and [`reading`]. //! +//! A ledger counts bytes; it cannot tell which of a region's allocations are +//! still live when the region ends. [`trace()`] records each request's block +//! address and size, in order, so that [`Trace::lifetimes`] can follow every +//! block from its allocation to its free; [the `trace` module](mod@trace) +//! documents the classification. +//! //! # Why each thread keeps its own ledger //! //! A test harness allocates on its own threads while a test runs. libtest's @@ -93,6 +99,13 @@ use std::mem::size_of; #[cfg(test)] mod tests; +pub mod trace; + +pub use trace::{ + Event, EventKind, Incomplete, Label, LabelLifetimes, Lifetimes, SegmentPeaks, Trace, labelled, + position, trace, untraced, +}; + /// The largest alignment that is not *over-aligned*: two machine words, which /// is 16 bytes on 64-bit targets. /// @@ -261,9 +274,12 @@ static ALLOCATOR: MeteredSystem = MeteredSystem; // SAFETY: Each method forwards its request unchanged to `System` and returns // `System`'s result unchanged, so `System` upholds every guarantee // `GlobalAlloc` requires of the returned memory. The bookkeeping touches only -// the calling thread's `Cell` through `record`, which never re-enters this -// allocator (see `LEDGER` for why reaching the ledger cannot) and never -// unwinds, as a global allocator must not. +// the calling thread's state: its `Cell` through `record`, which never +// re-enters this allocator (see `LEDGER` for why reaching the ledger cannot), +// and its trace through the `trace` module's recorders, which reach the event +// buffer only after a trace has initialized it and push only into spare +// capacity, so they never allocate either. Neither unwinds, as a global +// allocator must not. unsafe impl GlobalAlloc for MeteredSystem { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { // SAFETY: The caller upholds `alloc`'s contract for `layout`, which @@ -271,6 +287,7 @@ unsafe impl GlobalAlloc for MeteredSystem { let block = unsafe { System.alloc(layout) }; if !block.is_null() { record(|stats| stats.record_allocation(layout)); + trace::allocated(block.addr(), layout.size()); } block } @@ -281,6 +298,7 @@ unsafe impl GlobalAlloc for MeteredSystem { let block = unsafe { System.alloc_zeroed(layout) }; if !block.is_null() { record(|stats| stats.record_allocation(layout)); + trace::allocated(block.addr(), layout.size()); } block } @@ -291,6 +309,7 @@ unsafe impl GlobalAlloc for MeteredSystem { // forwarding to `System` frees it as allocated. unsafe { System.dealloc(ptr, layout) }; record(|stats| stats.record_free(layout.size())); + trace::freed(ptr.addr(), layout.size()); } unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { @@ -300,6 +319,7 @@ unsafe impl GlobalAlloc for MeteredSystem { // A failed reallocation leaves the old block live and unchanged. if !block.is_null() { record(|stats| stats.record_reallocation(layout, new_size)); + trace::reallocated(ptr.addr(), layout.size(), block.addr(), new_size); } block } diff --git a/crates/alloc-meter/src/tests.rs b/crates/alloc-meter/src/tests.rs index b89ab0893..74f5a7dc2 100644 --- a/crates/alloc-meter/src/tests.rs +++ b/crates/alloc-meter/src/tests.rs @@ -20,7 +20,7 @@ use proptest::sample::Index; use super::{OVER_ALIGNED_ABOVE, Stats, measure, reading, reset}; /// A heap block requested from the global allocator with an exact size and -/// alignment. +/// alignment, shared with the trace tests. /// /// Every pointer the allocator returns passes through [`black_box`] before the /// block keeps it. The optimizer may delete an allocation whose block nothing @@ -29,11 +29,11 @@ use super::{OVER_ALIGNED_ABOVE, Stats, measure, reading, reset}; /// then count a request the allocator never saw. `black_box` is best-effort by /// its own contract, but it is the standard library's tool for hiding a value /// from the optimizer. -struct Block { +pub(crate) struct Block { /// The block's start, as the allocator returned it. - ptr: NonNull, + pub(crate) ptr: NonNull, /// The layout the block currently has. - layout: Layout, + pub(crate) layout: Layout, } impl Block { @@ -44,7 +44,7 @@ impl Block { /// /// Panics if `size` is zero, which the allocator's contract forbids, or /// if `align` is not a power of two. - fn new(size: usize, align: usize, zeroed: bool) -> Self { + pub(crate) fn new(size: usize, align: usize, zeroed: bool) -> Self { assert!(size > 0, "a block has at least one byte"); let layout = Layout::from_size_align(size, align) .expect("a small size at a power-of-two alignment is a valid layout"); @@ -65,7 +65,7 @@ impl Block { /// # Panics /// /// Panics if `size` is zero, which the allocator's contract forbids. - fn resize(&mut self, size: usize) { + pub(crate) fn resize(&mut self, size: usize) { assert!(size > 0, "a block has at least one byte"); let layout = Layout::from_size_align(size, self.layout.align()) .expect("a small size at the block's alignment is a valid layout"); diff --git a/crates/alloc-meter/src/trace.rs b/crates/alloc-meter/src/trace.rs new file mode 100644 index 000000000..d0f594027 --- /dev/null +++ b/crates/alloc-meter/src/trace.rs @@ -0,0 +1,822 @@ +//! Allocation lifetimes over a traced region of one thread's work. +//! +//! A [`Stats`](crate::Stats) reading counts bytes, but it cannot say which +//! of the bytes a region allocated are still live when the region ends. A +//! *trace* records every allocator request the calling thread makes while +//! it runs, in order, with each block's address and size, so that a later +//! analysis can follow every block from its allocation to its free: +//! +//! ``` +//! let (trace, kept) = alloc_meter::trace(16, || { +//! drop(Vec::::with_capacity(32)); +//! Vec::::with_capacity(8) +//! }); +//! let lifetimes = trace.lifetimes().expect("sixteen events hold this region"); +//! let unlabelled = lifetimes.label(alloc_meter::Label::NONE); +//! assert_eq!(unlabelled.transient_peak, 32); +//! assert_eq!(unlabelled.surviving_bytes, 8); +//! drop(kept); +//! ``` +//! +//! # Classifying a block +//! +//! [`Trace::lifetimes`] sorts every block the region allocated into one of +//! two classes: +//! +//! - A *transient* block was allocated and freed inside the region. +//! - A *surviving* block was allocated inside the region and was still live +//! when it ended. +//! +//! A block allocated before the region began is neither, even if the region +//! frees it: its free matches no allocation in the trace, and the analysis +//! ignores it. So does a block allocated inside [`untraced`]. +//! [`Trace::survivors`] lists the surviving blocks themselves, so a caller can +//! check what owns them. +//! +//! The analysis reports, per [`Label`], the highest number of transient +//! bytes live at once over the region, the *transient peak*. Time is the +//! order of allocator requests. A reallocation counts as allocating the new +//! block and then freeing the old one, so the peak covers both blocks at +//! once, as [`Stats::peak_bytes`](crate::Stats::peak_bytes) does. +//! +//! # Labels +//! +//! [`labelled`] runs a closure with a label, and every block allocated +//! inside it carries that label. A block's bytes count toward the label it +//! was allocated under, whichever label is current when it is freed, so a +//! caller interleaving several independent computations on one thread can +//! attribute each block to the computation that allocated it. +//! +//! A label's transient peak is the highest its own bytes reach, so the peaks +//! of two labels need not occur together and their sum can exceed the peak +//! of both labels' bytes together. [`Trace::lifetimes_grouped`] classifies +//! the trace as though each label were replaced by the group a function +//! maps it to, so a caller who encodes several facts in one label (which +//! computation allocated a block, and what for) reads the peak of each group +//! as well as of each label. +//! +//! # Limits +//! +//! - A trace records into a buffer of the capacity [`trace`] is given, +//! allocated before the region begins, because the allocator must not +//! allocate while it records. A request that finds the buffer full is +//! counted in [`Trace::dropped`] instead, and [`Trace::lifetimes`] then +//! refuses to classify, since a lost free would turn a transient block +//! into a surviving one. +//! - A trace sees only the calling thread, like the ledger, and for the same +//! reasons (see [the crate docs](crate#why-each-thread-keeps-its-own-ledger)). +//! A block the region allocates and another thread frees looks like a +//! surviving block, unless the region later receives a new block at the +//! same address; the analysis then ends the first block's lifetime there, +//! and counts it in [`Lifetimes::reused_while_live`]. + +use std::cell::{Cell, RefCell}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; + +#[cfg(test)] +mod tests; + +/// The attribution a block carries: the label current when it was +/// allocated (see [the module docs](self#labels)). +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Label(pub u32); + +impl Label { + /// The label of a block allocated outside any [`labelled`] call. + pub const NONE: Self = Self(0); +} + +/// What one recorded allocator request did to one block. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum EventKind { + /// A block became live, by a fresh allocation or as the new block of a + /// reallocation. + Allocated, + /// A block was freed by a deallocation, or by a reallocation inside + /// [`untraced`], whose new block the trace omits. + Freed, + /// The old block of a traced reallocation was freed. The event that + /// follows it is always the new block's [`Allocated`](Self::Allocated), + /// and the transient peak counts the two blocks live together. + Resized, +} + +/// One recorded allocator request's effect on one block. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Event { + /// What happened to the block. + pub kind: EventKind, + /// The label current when the request was made. + pub label: Label, + /// The block's address. + pub address: usize, + /// The block's size in bytes, as its layout gives it. + pub size: usize, +} + +/// The calling thread's tracing state, read on every allocator request. +/// +/// A `Copy` value in a `Cell` with a const initializer needs no destructor, +/// so reaching it never allocates, as [`crate::LEDGER`]'s comment explains. +#[derive(Clone, Copy, Debug)] +struct Mode { + /// Whether a [`trace`] is running on this thread. + tracing: bool, + /// How many [`untraced`] calls enclose the current request; allocations + /// are omitted while it is nonzero. + untraced: u32, + /// The label current for new blocks. + label: Label, +} + +impl Mode { + /// The state every thread starts in. + const IDLE: Self = Self { + tracing: false, + untraced: 0, + label: Label::NONE, + }; +} + +/// A trace's preallocated event buffer, with the count of events it had no +/// room for. +#[derive(Debug)] +struct Buffer { + /// Recorded events, never grown while tracing. + events: Vec, + /// Events lost because `events` was full. + dropped: usize, +} + +// See the comment above `LEDGER` for the clippy allow. +thread_local! { + /// The calling thread's tracing state. + #[allow(clippy::missing_const_for_thread_local)] + static MODE: Cell = const { Cell::new(Mode::IDLE) }; + + /// The calling thread's event buffer. + /// + /// Unlike [`MODE`], the buffer owns a vector and so has a destructor, + /// whose registration on first access may allocate. The allocator + /// reaches the buffer only while [`MODE`] says a trace is running, and + /// [`trace`] touches the buffer before it sets that flag, so that first + /// access, and any allocation it makes, happens outside the allocator. + #[allow(clippy::missing_const_for_thread_local)] + static BUFFER: RefCell = const { + RefCell::new(Buffer { events: Vec::new(), dropped: 0 }) + }; +} + +/// Records one event when a trace is running on this thread. +/// +/// Called from inside the allocator, so it must neither allocate nor panic. +/// Every access is fallible rather than panicking, and the push happens +/// only while the buffer has spare capacity, so it never grows the vector. +fn record(kind: EventKind, address: usize, size: usize) { + let Ok(mode) = MODE.try_with(Cell::get) else { + return; + }; + if !mode.tracing || (kind == EventKind::Allocated && mode.untraced > 0) { + return; + } + let event = Event { + kind, + label: mode.label, + address, + size, + }; + let _ = BUFFER.try_with(|buffer| { + if let Ok(mut buffer) = buffer.try_borrow_mut() { + if buffer.events.len() < buffer.events.capacity() { + buffer.events.push(event); + } else { + buffer.dropped = buffer.dropped.saturating_add(1); + } + } + }); +} + +/// Whether allocations on this thread are currently omitted from its trace. +fn allocations_untraced() -> bool { + MODE.try_with(|mode| mode.get().untraced > 0) + .unwrap_or(true) +} + +/// Records a successful fresh allocation. +pub(crate) fn allocated(address: usize, size: usize) { + record(EventKind::Allocated, address, size); +} + +/// Records a deallocation. +pub(crate) fn freed(address: usize, size: usize) { + record(EventKind::Freed, address, size); +} + +/// Records a successful reallocation of the block at `old_address` to a new +/// block at `new_address`, which may be the same address. +/// +/// The old block's free comes first, so that an analysis matching frees to +/// allocations by address pairs it with the old block even when the system +/// resizes in place. Inside [`untraced`] the new block is omitted, and the +/// old block's free is recorded as a plain [`EventKind::Freed`], so that +/// every [`EventKind::Resized`] is followed by its new block. +pub(crate) fn reallocated( + old_address: usize, + old_size: usize, + new_address: usize, + new_size: usize, +) { + if allocations_untraced() { + record(EventKind::Freed, old_address, old_size); + } else { + record(EventKind::Resized, old_address, old_size); + record(EventKind::Allocated, new_address, new_size); + } +} + +/// Restores the tracing state a scoped call changed, when the call ends +/// normally or by unwinding. +struct Restore(Mode); + +impl Drop for Restore { + /// Puts back the state the scoped call found. + fn drop(&mut self) { + MODE.set(self.0); + } +} + +/// The events recorded over one [`trace`] region. +#[derive(Debug)] +pub struct Trace { + /// Every recorded event, in request order. + events: Vec, + /// Events lost to a full buffer. + dropped: usize, +} + +impl Trace { + /// Returns the recorded events, in the order the requests were made. + pub fn events(&self) -> &[Event] { + &self.events + } + + /// Returns how many events the trace lost because its buffer was full. + pub fn dropped(&self) -> usize { + self.dropped + } + + /// Classifies every block the region allocated as transient or + /// surviving, and finds each label's transient peak (see + /// [the module docs](self#classifying-a-block)). + /// + /// # Errors + /// + /// Returns [`Incomplete`] when the trace dropped events, since any + /// classification of an incomplete trace could be wrong. + pub fn lifetimes(&self) -> Result { + self.lifetimes_grouped(|label| label) + } + + /// Classifies every block as [`lifetimes`](Self::lifetimes) does, with + /// each event's label replaced by `group(label)` (see + /// [the module docs](self#labels)). + /// + /// Each group's transient peak is the highest number of transient bytes + /// live at once across every label in the group, which can be less than + /// the sum of those labels' own peaks. + /// + /// # Errors + /// + /// Returns [`Incomplete`] when the trace dropped events, as + /// [`lifetimes`](Self::lifetimes) does. + pub fn lifetimes_grouped( + &self, + group: impl Fn(Label) -> Label, + ) -> Result { + let events = self.complete()?; + Ok(Lifetimes::of_grouped(events, &resolve(events, group))) + } + + /// Returns the allocation event of every surviving block, in request + /// order: the blocks the region allocated that were live when it ended. + /// + /// A caller can check what owns the survivors by tracing the work that + /// should free them and matching its frees against these blocks. + /// + /// # Errors + /// + /// Returns [`Incomplete`] when the trace dropped events, as + /// [`lifetimes`](Self::lifetimes) does. + pub fn survivors(&self) -> Result, Incomplete> { + let events = self.complete()?; + let (transient, _) = transience(events); + Ok(events + .iter() + .zip(transient) + .filter(|(event, transient)| event.kind == EventKind::Allocated && !transient) + .map(|(event, _)| *event) + .collect()) + } + + /// Returns the peak transient level of each group of labels, and of + /// every group together, within each segment of the trace that `starts` + /// marks. + /// + /// An event's *level* for a group is the bytes of the group's transient + /// blocks live during it, counted as the classification counts them: a + /// block a reallocation moves stays live through the allocation of its + /// new block, and a block whose address is reused stays live through the + /// reusing allocation (see [`Lifetimes::reused_while_live`]). `group` + /// maps each label to the index of its group, below `groups`, or to + /// `None` to leave the label's blocks out. + /// + /// The segments partition the events in order: the first runs from the + /// trace's start to `starts[0]`, segment `k` from `starts[k - 1]` to + /// `starts[k]`, and the last from the last start to the trace's end, so + /// there is one more segment than starts. A segment holding no event, + /// such as one between equal starts or one beginning at or beyond the + /// trace's end, peaks at zero. A caller holding the trace's [`position`] + /// at moments of its own, such as the changes of an account it keeps + /// beside the trace, passes those positions as the starts. The account + /// then holds one value through each segment, and each group's peak + /// within the segment is the most its level reached against that value. + /// + /// # Panics + /// + /// Panics if `starts` decreases anywhere, or if `group` maps a label to + /// an index of `groups` or above. + /// + /// # Errors + /// + /// Returns [`Incomplete`] when the trace dropped events, as + /// [`lifetimes`](Self::lifetimes) does. + pub fn segment_peaks( + &self, + starts: &[usize], + groups: usize, + group: impl Fn(Label) -> Option, + ) -> Result { + let events = self.complete()?; + let resolved = resolve(events, |label| { + group(label).inspect(|&index| { + assert!( + index < groups, + "{label:?} maps to group {index}, beyond the {groups} groups" + ); + }) + }); + Ok(SegmentPeaks::of(events, starts, groups, &resolved)) + } + + /// Returns the events when the trace recorded every request, or the + /// refusal to classify an incomplete one. + fn complete(&self) -> Result<&[Event], Incomplete> { + if self.dropped > 0 { + return Err(Incomplete { + recorded: self.events.len(), + dropped: self.dropped, + }); + } + Ok(&self.events) + } +} + +/// The refusal to classify a trace that lost events to a full buffer. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Incomplete { + /// Events the trace recorded, which is its buffer's capacity. + pub recorded: usize, + /// Events it had no room for: a trace given `recorded + dropped` + /// capacity would have held them all. + pub dropped: usize, +} + +/// The blocks one label's allocations left, classified by lifetime. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct LabelLifetimes { + /// The highest number of transient bytes the label held live at once. + pub transient_peak: usize, + /// Blocks allocated and freed inside the region. + pub transient_blocks: usize, + /// Total bytes of those blocks, over the whole region. + pub transient_bytes: usize, + /// Blocks allocated inside the region and live when it ended. + pub surviving_blocks: usize, + /// Total bytes of those blocks. + pub surviving_bytes: usize, +} + +/// Every label's classified blocks over one trace. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Lifetimes { + /// Each label that allocated at least one block, with its blocks. + labels: BTreeMap, + /// Allocations whose address was already held by a live traced block, + /// which must have been freed where the trace could not see. + pub reused_while_live: usize, +} + +impl Lifetimes { + /// Returns the classified blocks of `label`, all zero if it allocated + /// nothing. + pub fn label(&self, label: Label) -> LabelLifetimes { + self.labels.get(&label).copied().unwrap_or_default() + } + + /// Classifies the blocks of an event sequence in request order. + #[cfg(test)] + fn of(events: &[Event]) -> Self { + Self::of_grouped(events, &resolve(events, |label| label)) + } + + /// Classifies the blocks of an event sequence in request order, with + /// each event's label replaced by its group in `groups`, which + /// [`resolve`] built from the same events. + /// + /// The first pass finds which blocks are transient ([`transience`]). The + /// second replays the events, pairing them the same way, and holds each + /// transient block's bytes live under its allocation's group from its + /// allocation to the event that ends it. A [`Resized`](EventKind::Resized) + /// free takes effect only after the next event, the new block's + /// allocation. + fn of_grouped(events: &[Event], groups: &Resolved