From ac0e18cab14070de86eb4482c0ded34963c26359 Mon Sep 17 00:00:00 2001 From: pmendes Date: Wed, 18 Dec 2024 12:32:58 +0000 Subject: [PATCH] Add CPU offload server --- Cargo.lock | 733 ++++++++++-------- crates/daphne-server/Cargo.toml | 5 +- .../docker/example-service.Dockerfile | 7 + .../examples/configuration-cpu-offload.toml | 34 + crates/daphne-server/src/roles/helper.rs | 4 +- .../src/router/compute_offload.rs | 84 ++ crates/daphne-server/src/router/mod.rs | 5 +- crates/daphne-service-utils/Cargo.toml | 2 + crates/daphne-service-utils/build.rs | 23 +- .../src/compute_offload/compute_offload.capnp | 120 +++ .../src/compute_offload/mod.rs | 488 ++++++++++++ crates/daphne-service-utils/src/lib.rs | 17 +- crates/daphne-worker-test/Cargo.toml | 4 +- .../docker/aggregator.Dockerfile | 2 +- .../docker/docker-compose-e2e.yaml | 11 + crates/daphne-worker-test/src/lib.rs | 48 +- crates/daphne-worker/Cargo.toml | 4 +- crates/daphne-worker/src/aggregator/mod.rs | 44 +- .../src/aggregator/roles/aggregator.rs | 6 + .../src/aggregator/roles/helper.rs | 6 +- .../src/aggregator/router/helper.rs | 72 +- crates/daphne/src/error/aborts.rs | 4 +- crates/daphne/src/error/mod.rs | 14 +- crates/daphne/src/hpke.rs | 4 +- crates/daphne/src/protocol/report_init.rs | 6 +- .../daphne/src/roles/helper/handle_agg_job.rs | 2 +- crates/daphne/src/roles/helper/mod.rs | 4 +- crates/daphne/src/testing/mod.rs | 8 +- crates/daphne/src/vdaf/mod.rs | 12 + 29 files changed, 1389 insertions(+), 384 deletions(-) create mode 100644 crates/daphne-server/examples/configuration-cpu-offload.toml create mode 100644 crates/daphne-server/src/router/compute_offload.rs create mode 100644 crates/daphne-service-utils/src/compute_offload/compute_offload.capnp create mode 100644 crates/daphne-service-utils/src/compute_offload/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1ef81975f..cfae1f3fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -95,9 +95,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -110,43 +110,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "asn1-rs" @@ -160,7 +160,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 1.0.63", + "thiserror 1.0.69", "time", ] @@ -195,9 +195,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -212,27 +212,26 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.8.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" dependencies = [ "aws-lc-sys", - "mirai-annotations", "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.20.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" dependencies = [ "bindgen", "cc", @@ -245,9 +244,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -269,18 +268,19 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper", "tokio", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -291,7 +291,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper", "tower-layer", "tower-service", "tracing", @@ -299,25 +299,26 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" +checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum", "axum-core", "bytes", + "fastrand", "futures-util", "headers", "http", "http-body", "http-body-util", "mime", + "multer", "pin-project-lite", "serde", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -328,17 +329,17 @@ checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -373,9 +374,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags 2.6.0", "cexpr", @@ -435,9 +436,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.17.1" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" [[package]] name = "byteorder" @@ -447,9 +448,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cap" @@ -483,9 +484,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.15" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -507,6 +508,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -533,9 +540,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -596,9 +603,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -606,9 +613,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -618,9 +625,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -630,24 +637,24 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "config" @@ -686,9 +693,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constcat" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2e5af989b1955b092db01462980c0a286217f86817e12b2c09aea46bd03651" +checksum = "4938185353434999ef52c81753c8cca8955ed38042fc29913db3751916f3b7ab" [[package]] name = "core-foundation" @@ -700,6 +707,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -708,9 +725,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -856,8 +873,8 @@ dependencies = [ "prometheus", "rand", "reqwest", - "rustls 0.23.12", - "rustls-native-certs", + "rustls 0.23.20", + "rustls-native-certs 0.7.3", "rustls-pemfile", "sentry", "serde", @@ -897,7 +914,7 @@ dependencies = [ "serde_json", "strum", "subtle", - "thiserror 1.0.63", + "thiserror 1.0.69", "tokio", "tracing", "url", @@ -926,14 +943,15 @@ dependencies = [ "prio 0.17.0-alpha.0", "prometheus", "rand", + "rayon", "rcgen", "reqwest", "serde", "serde_json", "serde_yaml", - "thiserror 1.0.63", + "thiserror 1.0.69", "tokio", - "tower", + "tower 0.4.13", "tracing", "tracing-subscriber", "url", @@ -952,6 +970,7 @@ dependencies = [ "prio 0.17.0-alpha.0", "rand", "serde", + "serde_json", "url", ] @@ -987,9 +1006,9 @@ dependencies = [ "serde-wasm-bindgen 0.6.5", "serde_json", "static_assertions", - "thiserror 1.0.63", + "thiserror 1.0.69", "tokio", - "tower", + "tower 0.4.13", "tower-service", "tracing", "tracing-core", @@ -1003,10 +1022,12 @@ dependencies = [ name = "daphne-worker-test" version = "0.3.0" dependencies = [ + "async-trait", "cap", "cfg-if", "console_error_panic_hook", "daphne-worker", + "futures", "prometheus", "tracing", "worker", @@ -1180,6 +1201,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bbadc628dc286b9ae02f0cb0f5411c056eb7487b72f0083203f115de94060" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1188,14 +1218,20 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "ff" version = "0.13.0" @@ -1265,9 +1301,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1280,9 +1316,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1290,15 +1326,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1307,15 +1343,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1324,21 +1360,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1388,9 +1424,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1449,9 +1485,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "headers" @@ -1483,12 +1519,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1584,9 +1614,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1618,9 +1648,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1630,9 +1660,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -1651,28 +1681,28 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", "hyper", "hyper-util", - "rustls 0.23.12", - "rustls-native-certs", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots 0.26.3", + "webpki-roots 0.26.7", ] [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1683,16 +1713,15 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1852,12 +1881,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -1871,9 +1900,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" @@ -1881,7 +1910,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -1912,9 +1941,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -1927,10 +1956,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1968,15 +1998,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -2057,11 +2087,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -2072,21 +2102,31 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07" [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", ] [[package]] -name = "mirai-annotations" -version = "1.12.0" +name = "multer" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] [[package]] name = "nom" @@ -2169,9 +2209,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] @@ -2187,9 +2227,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" @@ -2221,9 +2261,9 @@ dependencies = [ [[package]] name = "os_info" -version = "3.8.2" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +checksum = "e5ca711d8b83edbb00b44d504503cd247c9c0bd8b0fa2694f2a1a3d8165379ce" dependencies = [ "log", "serde", @@ -2289,9 +2329,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pem" @@ -2320,20 +2360,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 1.0.63", + "thiserror 2.0.6", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -2341,9 +2381,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", @@ -2354,9 +2394,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -2365,18 +2405,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", @@ -2385,9 +2425,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2407,9 +2447,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -2420,15 +2460,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -2473,9 +2513,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", "syn 2.0.90", @@ -2517,7 +2557,7 @@ dependencies = [ "sha2", "sha3", "subtle", - "thiserror 1.0.63", + "thiserror 1.0.69", "zipf", ] @@ -2547,7 +2587,7 @@ dependencies = [ "sha2", "sha3", "subtle", - "thiserror 2.0.8", + "thiserror 2.0.6", "zipf", ] @@ -2572,7 +2612,7 @@ dependencies = [ "memchr", "parking_lot", "protobuf", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -2583,50 +2623,54 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "quinn" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", - "rustls 0.23.12", + "rustc-hash 2.1.0", + "rustls 0.23.20", "socket2", - "thiserror 1.0.63", + "thiserror 2.0.6", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring", - "rustc-hash 2.0.0", - "rustls 0.23.12", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "rustls-pki-types", "slab", - "thiserror 1.0.63", + "thiserror 2.0.6", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2708,23 +2752,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -2738,13 +2782,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2755,15 +2799,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -2784,14 +2828,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.12", - "rustls-native-certs", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper", "tokio", "tokio-rustls", "tower-service", @@ -2799,7 +2843,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.3", + "webpki-roots 0.26.7", "windows-registry", ] @@ -2863,15 +2907,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -2887,15 +2931,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2912,48 +2956,62 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.7", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.0.1", ] [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -2967,9 +3025,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "aws-lc-rs", "ring", @@ -2979,9 +3037,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -3000,11 +3058,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3044,7 +3102,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -3052,9 +3123,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -3169,7 +3240,7 @@ dependencies = [ "rand", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", "time", "url", "uuid", @@ -3177,9 +3248,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -3208,9 +3279,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -3219,9 +3290,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3347,9 +3418,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3441,15 +3512,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -3485,27 +3550,27 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.63", + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "2.0.8" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.8", + "thiserror-impl 2.0.6", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -3514,9 +3579,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.8" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", @@ -3541,9 +3606,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -3562,9 +3627,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -3629,9 +3694,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.3" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3657,20 +3722,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.12", - "rustls-pki-types", + "rustls 0.23.20", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3698,12 +3762,26 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio", "tower-layer", "tower-service", "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -3718,9 +3796,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -3730,9 +3808,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -3741,9 +3819,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -3762,9 +3840,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -3772,9 +3850,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -3805,9 +3883,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uname" @@ -3820,15 +3898,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -3854,17 +3932,17 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64 0.22.1", "log", "once_cell", - "rustls 0.23.12", + "rustls 0.23.20", "rustls-pki-types", "url", - "webpki-roots 0.26.3", + "webpki-roots 0.26.7", ] [[package]] @@ -3899,9 +3977,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "serde", ] @@ -3945,21 +4023,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", - "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", @@ -3971,21 +4048,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3993,9 +4071,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -4006,18 +4084,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -4028,9 +4103,19 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4054,9 +4139,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -4276,7 +4361,7 @@ dependencies = [ "serde", "serde-wasm-bindgen 0.5.0", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", "wasm-bindgen", "wasm-bindgen-futures", ] @@ -4355,7 +4440,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 1.0.63", + "thiserror 1.0.69", "time", ] diff --git a/crates/daphne-server/Cargo.toml b/crates/daphne-server/Cargo.toml index b1e9150fc..598c5691f 100644 --- a/crates/daphne-server/Cargo.toml +++ b/crates/daphne-server/Cargo.toml @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Cloudflare, Inc. All rights reserved. +# Copyright (c) 2025 Cloudflare, Inc. All rights reserved. # SPDX-License-Identifier: BSD-3-Clause [package] @@ -17,7 +17,7 @@ all-features = true [dependencies] daphne = { path = "../daphne" } -daphne-service-utils = { path = "../daphne-service-utils", features = ["durable_requests"] } +daphne-service-utils = { path = "../daphne-service-utils", features = ["durable_requests", "compute-offload"] } either.workspace = true futures.workspace = true hex.workspace = true @@ -33,6 +33,7 @@ tokio.workspace = true tower = { workspace = true, features = ["util"] } tracing.workspace = true url.workspace = true +rayon.workspace = true [dependencies.axum] workspace = true diff --git a/crates/daphne-server/docker/example-service.Dockerfile b/crates/daphne-server/docker/example-service.Dockerfile index 207125277..d18e1d749 100644 --- a/crates/daphne-server/docker/example-service.Dockerfile +++ b/crates/daphne-server/docker/example-service.Dockerfile @@ -31,3 +31,10 @@ RUN sed -i 's/localhost/leader_storage/g' configuration.toml COPY --from=builder /dap/target/debug/examples/service . ENTRYPOINT ["./service"] + +FROM debian:bookworm AS compute-offload + +COPY ./crates/daphne-server/examples/configuration-cpu-offload.toml configuration.toml +COPY --from=builder /dap/target/debug/examples/service . + +ENTRYPOINT ["./service"] diff --git a/crates/daphne-server/examples/configuration-cpu-offload.toml b/crates/daphne-server/examples/configuration-cpu-offload.toml new file mode 100644 index 000000000..67f79481a --- /dev/null +++ b/crates/daphne-server/examples/configuration-cpu-offload.toml @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Cloudflare, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause + +port = 5000 + +# None of these settings are relevant and can be deleted later when +# daphne-server stops being an aggregator +[storage_proxy] +url = "http://localhost:4001" +# SECRET: This is a test secret. In production, we'll generate and securely provision the token. +auth_token = 'this-is-the-storage-proxy-auth-token' + +[service] +env = "oxy" +role = "helper" +max_batch_duration = 360000 +min_batch_interval_start = 259200 +max_batch_interval_end = 259200 +supported_hpke_kems = ["x25519_hkdf_sha256"] +default_version = "v09" +report_storage_epoch_duration = 300000 +base_url = "http://127.0.0.1:8788" +default_num_agg_span_shards = 4 + +[service.taskprov] +peer_auth.leader.expected_token = "I-am-the-leader" # SECRET +vdaf_verify_key_init = "b029a72fa327931a5cb643dcadcaafa098fcbfac07d990cb9e7c9a8675fafb18" # SECRET +hpke_collector_config = """{ + "id": 23, + "kem_id": "p256_hkdf_sha256", + "kdf_id": "hkdf_sha256", + "aead_id": "aes128_gcm", + "public_key": "047dab625e0d269abcc28c611bebf5a60987ddf7e23df0e0aa343e5774ad81a1d0160d9252b82b4b5c52354205f5ec945645cb79facff8d85c9c31b490cdf35466" +}""" diff --git a/crates/daphne-server/src/roles/helper.rs b/crates/daphne-server/src/roles/helper.rs index 34e6a468e..12fe1f8ae 100644 --- a/crates/daphne-server/src/roles/helper.rs +++ b/crates/daphne-server/src/roles/helper.rs @@ -10,12 +10,12 @@ use daphne::{ #[async_trait] impl DapHelper for crate::App { - async fn assert_agg_job_is_immutable( + async fn assert_agg_job_is_legal( &self, _id: AggregationJobId, _version: DapVersion, _task_id: &TaskId, - _req: &AggregationJobRequestHash, + _req_hash: &AggregationJobRequestHash, ) -> Result<(), DapError> { // the server implementation can't check for this Ok(()) diff --git a/crates/daphne-server/src/router/compute_offload.rs b/crates/daphne-server/src/router/compute_offload.rs new file mode 100644 index 000000000..77506ab82 --- /dev/null +++ b/crates/daphne-server/src/router/compute_offload.rs @@ -0,0 +1,84 @@ +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause + +use crate::App; +use axum::{async_trait, extract::FromRequest, response::IntoResponse, routing::post}; +use daphne::{error::DapAbort, InitializedReport}; +use daphne_service_utils::{ + capnproto::{CapnprotoPayloadDecode, CapnprotoPayloadDecodeExt, CapnprotoPayloadEncodeExt}, + compute_offload::{InitializeReports, InitializedReports}, +}; +use http::StatusCode; +use prio::codec::ParameterizedDecode; +use rayon::iter::{IntoParallelIterator as _, ParallelIterator}; + +pub(super) fn add_routes(router: super::Router) -> super::Router { + router.route( + "/compute_offload/initialize_reports", + post(initialize_reports), + ) +} + +struct CapnprotoExtractor(T); + +#[async_trait] +impl FromRequest for CapnprotoExtractor +where + T: CapnprotoPayloadDecode, +{ + type Rejection = StatusCode; + + async fn from_request( + req: http::Request, + _state: &S, + ) -> Result { + let bytes = axum::body::to_bytes(req.into_body(), usize::MAX) + .await + .map_err(|_| StatusCode::BAD_REQUEST)?; + let t = T::decode_from_bytes(&bytes).map_err(|_| StatusCode::BAD_REQUEST)?; + + Ok(CapnprotoExtractor(t)) + } +} + +#[tracing::instrument(skip_all, fields(%task_id, report_count = prep_inits.len()))] +async fn initialize_reports( + CapnprotoExtractor(InitializeReports { + hpke_keys, + valid_report_range, + task_id, + task_config, + agg_param, + prep_inits, + }): CapnprotoExtractor>, +) -> impl IntoResponse { + tracing::info!("initializing reports"); + let initialized_reports = prep_inits + .into_par_iter() + .map(|prep_init| { + InitializedReport::from_leader( + &hpke_keys.as_ref(), + valid_report_range.clone(), + &task_id, + &task_config, + prep_init.report_share, + prep_init.payload, + &daphne::DapAggregationParam::get_decoded_with_param(&task_config.vdaf, &agg_param) + .map_err(|e| DapAbort::from_codec_error(e, task_id))?, + ) + }) + .collect::, _>>(); + + match initialized_reports { + Ok(reports) => { + let body = InitializedReports { + vdaf: task_config.vdaf.into_owned(), + reports, + } + .encode_to_bytes(); + + (StatusCode::OK, body).into_response() + } + Err(error) => (StatusCode::BAD_REQUEST, axum::Json(error)).into_response(), + } +} diff --git a/crates/daphne-server/src/router/mod.rs b/crates/daphne-server/src/router/mod.rs index b7a1ada13..475e02830 100644 --- a/crates/daphne-server/src/router/mod.rs +++ b/crates/daphne-server/src/router/mod.rs @@ -1,7 +1,8 @@ -// Copyright (c) 2024 Cloudflare, Inc. All rights reserved. +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause mod aggregator; +mod compute_offload; mod extractor; mod helper; mod leader; @@ -99,6 +100,8 @@ pub fn new(role: DapAggregatorRole, aggregator: App) -> axum::Router<()> { DapAggregatorRole::Helper => helper::add_helper_routes(router), }; + let router = compute_offload::add_routes(router); + #[cfg(feature = "test-utils")] let router = test_routes::add_test_routes(router, role); diff --git a/crates/daphne-service-utils/Cargo.toml b/crates/daphne-service-utils/Cargo.toml index f906bf3c7..a443f77ba 100644 --- a/crates/daphne-service-utils/Cargo.toml +++ b/crates/daphne-service-utils/Cargo.toml @@ -17,6 +17,7 @@ daphne = { path = "../daphne", default-features = false } prio_draft09 = { workspace = true, optional = true } prio = { workspace = true, optional = true } serde.workspace = true +serde_json = { workspace = true, optional = true } url = { workspace = true, optional = true } [dev-dependencies] @@ -28,6 +29,7 @@ capnpc = { workspace = true, optional = true } [features] test-utils = ["dep:url", "daphne/prometheus", "daphne/test-utils"] +compute-offload = ["dep:capnp", "dep:capnpc", "dep:serde_json", "dep:prio"] durable_requests = [ "dep:capnp", "dep:capnpc", diff --git a/crates/daphne-service-utils/build.rs b/crates/daphne-service-utils/build.rs index 2e78bf6aa..317e18715 100644 --- a/crates/daphne-service-utils/build.rs +++ b/crates/daphne-service-utils/build.rs @@ -2,11 +2,20 @@ // SPDX-License-Identifier: BSD-3-Clause fn main() { - #[cfg(feature = "durable_requests")] - ::capnpc::CompilerCommand::new() - .file("./src/capnproto/base.capnp") - .file("./src/durable_requests/durable_request.capnp") - .file("./src/durable_requests/bindings/aggregation_job_store.capnp") - .run() - .expect("compiling schema"); + #[cfg(any(feature = "durable_requests", feature = "compute-offload"))] + { + let mut compiler = ::capnpc::CompilerCommand::new(); + + compiler.file("./src/capnproto/base.capnp"); + + #[cfg(feature = "durable_requests")] + compiler + .file("./src/durable_requests/durable_request.capnp") + .file("./src/durable_requests/bindings/aggregation_job_store.capnp"); + + #[cfg(feature = "compute-offload")] + compiler.file("./src/compute_offload/compute_offload.capnp"); + + compiler.run().expect("compiling schema"); + } } diff --git a/crates/daphne-service-utils/src/compute_offload/compute_offload.capnp b/crates/daphne-service-utils/src/compute_offload/compute_offload.capnp new file mode 100644 index 000000000..3fa6bea48 --- /dev/null +++ b/crates/daphne-service-utils/src/compute_offload/compute_offload.capnp @@ -0,0 +1,120 @@ +# Copyright (c) 2025 Cloudflare, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause + +@0xd932f3d934afce3b; + +# Utilities + +using Base = import "../capnproto/base.capnp"; + +using VdafConfig = Text; # json encoded +using VdafVerifyKey = Base.U8L32; + +struct TimeRange @0xf0d27aaa9b1959f7 { + start @0 :UInt64; + end @1 :UInt64; +} + +# Top level message +struct InitializeReports @0x90aadb2f44c9fb78 { + hpkeKeys @0 :List(HpkeReceiverConfig); + validReportRange @1 :TimeRange; + taskId @2 :Base.TaskId; + taskConfig @3 :PartialDapTaskConfig; + aggParam @4 :Data; # encoded + prepInits @5 :List(PrepareInit); +} + +struct HpkeReceiverConfig @0xeec9b4a50458edb7 { + struct HpkeConfig @0xa546066418a5cdc7 { + enum HpkeKemId @0xf4bbeaed8d1fd18a { + p256HkdfSha256 @0; x25519HkdfSha256 @1; + } + enum HpkeKdfId @0x9336afc63df27ba3 { hkdfSha256 @0; } + enum HpkeAeadId @0xd68d403e118c806c { aes128Gcm @0; } + + id @0 :UInt8; + kemId @1 :HpkeKemId; + kdfId @2 :HpkeKdfId; + aeadId @3 :HpkeAeadId; + publicKey @4 :Data; + } + + config @0 :HpkeConfig; + privateKey @1 :Data; +} + +struct PartialDapTaskConfig @0xdcc9bf18fc62d406 { + + version @0 :Base.DapVersion; + methodIsTaskprov @1 :Bool; + notAfter @2 :Base.Time; + vdaf @3 :VdafConfig; + vdafVerifyKey @4 :VdafVerifyKey; +} + +struct ReportMetadata @0xefba178ad4584bc4 { + + id @0 :Base.ReportId; + time @1 :Base.Time; +} + +struct PrepareInit @0x8192568cb3d03f59 { + + struct HpkeCiphertext @0xf0813319decf7eaf { + configId @0 :UInt8; + enc @1 :Data; + payload @2 :Data; + } + + struct ReportShare @0xb4134aa2db41ef60 { + reportMetadata @0 :ReportMetadata; + publicShare @1 :Data; + encryptedInputShare @2 :HpkeCiphertext; + } + + reportShare @0 :ReportShare; + payload @1 :Data; +} + + + +struct InitializedReports { + struct InitializedReport { + using VdafPrepShare = Data; + using VdafPrepState = Data; + + enum ReportError { + reserved @0; + batchCollected @1; + reportReplayed @2; + reportDropped @3; + hpkeUnknownConfigId @4; + hpkeDecryptError @5; + vdafPrepError @6; + batchSaturated @7; + taskExpired @8; + invalidMessage @9; + reportTooEarly @10; + taskNotStarted @11; + } + + + union { + ready :group { + metadata @0 :ReportMetadata; + publicShare @1 :Data; + prepShare @2 :VdafPrepShare; + prepState @3 :VdafPrepState; + peerPrepShare @4 :Data; + } + rejected :group { + metadata @5 :ReportMetadata; + failure @6 :ReportError; + } + } + } + + vdafConfig @0 :VdafConfig; + reports @1 :List(InitializedReport); +} diff --git a/crates/daphne-service-utils/src/compute_offload/mod.rs b/crates/daphne-service-utils/src/compute_offload/mod.rs new file mode 100644 index 000000000..dcc1485f6 --- /dev/null +++ b/crates/daphne-service-utils/src/compute_offload/mod.rs @@ -0,0 +1,488 @@ +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause + +use crate::{ + capnproto::{ + decode_list, encode_list, usize_to_capnp_len, CapnprotoPayloadDecode, + CapnprotoPayloadEncode, + }, + compute_offload_capnp::{ + hpke_receiver_config::{self, hpke_config}, + initialize_reports, + initialized_reports::{self, initialized_report}, + partial_dap_task_config, prepare_init, report_metadata, time_range, + }, +}; +use daphne::{ + constants::DapAggregatorRole, + hpke::{HpkeConfig, HpkeReceiverConfig}, + messages::{self, HpkeCiphertext, PrepareInit, ReportMetadata, ReportShare, TaskId}, + vdaf::{VdafConfig, VdafPrepShare, VdafPrepState}, + InitializedReport, PartialDapTaskConfigForReportInit, WithPeerPrepShare, +}; +use prio::codec::{Encode, ParameterizedDecode, ParameterizedEncode}; +use std::{borrow::Cow, ops::Range}; + +pub struct InitializeReports<'s> { + pub hpke_keys: Cow<'s, [HpkeReceiverConfig]>, + /// Output of [`DapAggregator::valid_report_time_range`](daphne::roles::DapAggregator) at the + /// start of the aggregation job. + pub valid_report_range: Range, + pub task_id: TaskId, + pub task_config: PartialDapTaskConfigForReportInit<'s>, + pub agg_param: Cow<'s, [u8]>, + pub prep_inits: Vec, +} + +impl CapnprotoPayloadEncode for InitializeReports<'_> { + type Builder<'a> = initialize_reports::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let InitializeReports { + hpke_keys, + valid_report_range, + task_id, + task_config, + agg_param, + prep_inits, + } = self; + encode_list( + hpke_keys.as_ref(), + builder + .reborrow() + .init_hpke_keys(usize_to_capnp_len(hpke_keys.len())), + ); + valid_report_range.encode_to_builder(builder.reborrow().init_valid_report_range()); + task_id.encode_to_builder(builder.reborrow().init_task_id()); + task_config.encode_to_builder(builder.reborrow().init_task_config()); + builder.set_agg_param(agg_param); + encode_list( + prep_inits, + builder.init_prep_inits( + prep_inits + .len() + .try_into() + .expect("can't serialize more than u32::MAX prep_inits"), + ), + ); + } +} + +impl CapnprotoPayloadDecode for InitializeReports<'static> { + type Reader<'a> = initialize_reports::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + let task_config = <_>::decode_from_reader(reader.get_task_config()?)?; + + Ok(Self { + hpke_keys: Cow::Owned(decode_list::( + reader.get_hpke_keys()?, + )?), + valid_report_range: <_>::decode_from_reader(reader.get_valid_report_range()?)?, + task_id: <_>::decode_from_reader(reader.get_task_id()?)?, + agg_param: Cow::Owned(reader.get_agg_param()?.to_vec()), + task_config, + prep_inits: decode_list::(reader.get_prep_inits()?)?, + }) + } +} + +impl CapnprotoPayloadEncode for HpkeReceiverConfig { + type Builder<'a> = hpke_receiver_config::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let HpkeReceiverConfig { + config, + private_key, + } = self; + config.encode_to_builder(builder.reborrow().init_config()); + builder.set_private_key(private_key.as_slice()); + } +} + +impl CapnprotoPayloadDecode for HpkeReceiverConfig { + type Reader<'a> = hpke_receiver_config::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(Self { + config: <_>::decode_from_reader(reader.get_config()?)?, + private_key: reader.get_private_key()?.into(), + }) + } +} + +impl CapnprotoPayloadEncode for HpkeConfig { + type Builder<'a> = hpke_config::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let HpkeConfig { + id, + kem_id, + kdf_id, + aead_id, + public_key, + } = self; + builder.set_id(*id); + builder.set_kem_id(match kem_id { + daphne::hpke::HpkeKemId::P256HkdfSha256 => hpke_config::HpkeKemId::P256HkdfSha256, + daphne::hpke::HpkeKemId::X25519HkdfSha256 => hpke_config::HpkeKemId::X25519HkdfSha256, + daphne::hpke::HpkeKemId::NotImplemented(n) => { + unimplemented!("HpkeKemId({n})") + } + }); + builder.set_kdf_id(match kdf_id { + daphne::hpke::HpkeKdfId::HkdfSha256 => hpke_config::HpkeKdfId::HkdfSha256, + daphne::hpke::HpkeKdfId::NotImplemented(n) => { + unimplemented!("HpkeKdfId({n})") + } + }); + builder.set_aead_id(match aead_id { + daphne::hpke::HpkeAeadId::Aes128Gcm => hpke_config::HpkeAeadId::Aes128Gcm, + daphne::hpke::HpkeAeadId::NotImplemented(n) => { + unimplemented!("HpkeAeadId({n})") + } + }); + builder.set_public_key(public_key.as_slice()); + } +} + +impl CapnprotoPayloadDecode for HpkeConfig { + type Reader<'a> = hpke_config::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(Self { + id: reader.get_id(), + kem_id: match reader.get_kem_id()? { + hpke_config::HpkeKemId::P256HkdfSha256 => daphne::hpke::HpkeKemId::P256HkdfSha256, + hpke_config::HpkeKemId::X25519HkdfSha256 => { + daphne::hpke::HpkeKemId::X25519HkdfSha256 + } + }, + kdf_id: match reader.get_kdf_id()? { + hpke_config::HpkeKdfId::HkdfSha256 => daphne::hpke::HpkeKdfId::HkdfSha256, + }, + aead_id: match reader.get_aead_id()? { + hpke_config::HpkeAeadId::Aes128Gcm => daphne::hpke::HpkeAeadId::Aes128Gcm, + }, + public_key: reader.get_public_key()?.into(), + }) + } +} + +impl CapnprotoPayloadEncode for Range { + type Builder<'a> = time_range::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + builder.set_start(self.start); + builder.set_end(self.end); + } +} + +impl CapnprotoPayloadDecode for Range { + type Reader<'a> = time_range::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(reader.get_start()..reader.get_end()) + } +} + +impl CapnprotoPayloadEncode for PartialDapTaskConfigForReportInit<'_> { + type Builder<'a> = partial_dap_task_config::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let PartialDapTaskConfigForReportInit { + not_after, + method_is_taskprov, + version, + vdaf, + vdaf_verify_key, + } = self; + builder.set_not_after(*not_after); + builder.set_method_is_taskprov(*method_is_taskprov); + builder.set_version((*version).into()); + builder.set_vdaf(encode_vdaf_config(vdaf).as_slice().into()); + vdaf_verify_key + .inner() + .encode_to_builder(builder.reborrow().init_vdaf_verify_key()); + } +} + +impl CapnprotoPayloadDecode for PartialDapTaskConfigForReportInit<'static> { + type Reader<'a> = partial_dap_task_config::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(Self { + not_after: reader.get_not_after(), + method_is_taskprov: reader.get_method_is_taskprov(), + version: reader.get_version()?.into(), + vdaf: Cow::Owned(<_>::decode_from_reader(reader.reborrow().get_vdaf()?)?), + vdaf_verify_key: <_>::from(<[u8; 32]>::decode_from_reader( + reader.get_vdaf_verify_key()?, + )?), + }) + } +} + +fn encode_vdaf_config(vdaf: &VdafConfig) -> Vec { + serde_json::to_vec(vdaf).unwrap() +} + +impl CapnprotoPayloadDecode for VdafConfig { + type Reader<'a> = capnp::text::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + serde_json::from_slice(reader.as_bytes()).map_err(to_capnp) + } +} + +impl CapnprotoPayloadEncode for PrepareInit { + type Builder<'a> = prepare_init::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let PrepareInit { + report_share, + payload, + } = self; + builder.set_payload(payload); + { + let ReportShare { + report_metadata, + public_share, + encrypted_input_share, + } = report_share; + let mut builder = builder.init_report_share(); + builder.set_public_share(public_share); + report_metadata.encode_to_builder(builder.reborrow().init_report_metadata()); + { + let HpkeCiphertext { + config_id, + enc, + payload, + } = encrypted_input_share; + let mut builder = builder.reborrow().init_encrypted_input_share(); + builder.set_config_id(*config_id); + builder.set_enc(enc); + builder.set_payload(payload); + } + } + } +} + +impl CapnprotoPayloadDecode for PrepareInit { + type Reader<'a> = prepare_init::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(Self { + report_share: { + let reader = reader.get_report_share()?; + ReportShare { + report_metadata: <_>::decode_from_reader(reader.get_report_metadata()?)?, + public_share: reader.get_public_share()?.to_vec(), + encrypted_input_share: { + let reader = reader.get_encrypted_input_share()?; + HpkeCiphertext { + config_id: reader.get_config_id(), + enc: reader.get_enc()?.to_vec(), + payload: reader.get_payload()?.to_vec(), + } + }, + } + }, + payload: reader.get_payload()?.to_vec(), + }) + } +} + +impl CapnprotoPayloadEncode for ReportMetadata { + type Builder<'a> = report_metadata::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let Self { id, time } = self; + id.encode_to_builder(builder.reborrow().init_id()); + builder.set_time(*time); + } +} + +impl CapnprotoPayloadDecode for ReportMetadata { + type Reader<'a> = report_metadata::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + Ok(Self { + id: <_>::decode_from_reader(reader.get_id()?)?, + time: reader.get_time(), + }) + } +} + +impl CapnprotoPayloadEncode for InitializedReport { + type Builder<'a> = initialized_reports::initialized_report::Builder<'a>; + + fn encode_to_builder(&self, builder: Self::Builder<'_>) { + match self { + InitializedReport::Ready { + metadata, + public_share, + prep_share, + prep_state, + peer_prep_share, + } => { + let mut builder = builder.init_ready(); + metadata.encode_to_builder(builder.reborrow().init_metadata()); + builder.set_public_share(public_share); + let mut buffer = Vec::new(); + { + prep_share + .encode_with_param(prep_state, &mut buffer) + .unwrap(); + builder.set_prep_share(&buffer); + buffer.clear(); + } + { + prep_state.encode(&mut buffer).unwrap(); + builder.set_prep_state(&buffer); + buffer.clear(); + } + builder.set_peer_prep_share(peer_prep_share); + } + InitializedReport::Rejected { + metadata, + report_err, + } => { + let mut builder = builder.init_rejected(); + metadata.encode_to_builder(builder.reborrow().init_metadata()); + builder.set_failure((*report_err).into()); + } + } + } +} + +pub struct InitializedReports { + pub vdaf: VdafConfig, + pub reports: Vec>, +} + +impl CapnprotoPayloadEncode for InitializedReports { + type Builder<'a> = initialized_reports::Builder<'a>; + + fn encode_to_builder(&self, mut builder: Self::Builder<'_>) { + let Self { vdaf, reports } = self; + builder.set_vdaf_config(encode_vdaf_config(vdaf).as_slice().into()); + encode_list( + reports, + builder.init_reports(usize_to_capnp_len(reports.len())), + ); + } +} + +impl CapnprotoPayloadDecode for InitializedReports { + type Reader<'a> = initialized_reports::Reader<'a>; + + fn decode_from_reader(reader: Self::Reader<'_>) -> capnp::Result + where + Self: Sized, + { + let vdaf = <_>::decode_from_reader(reader.get_vdaf_config()?)?; + Ok(Self { + reports: reader + .get_reports()? + .into_iter() + .map(|report| match report.which()? { + initialized_report::Which::Ready(reader) => { + let prep_state = VdafPrepState::get_decoded_with_param( + &(&vdaf, DapAggregatorRole::Helper), + reader.get_prep_state()?, + ) + .map_err(to_capnp)?; + Ok(InitializedReport::Ready { + metadata: <_>::decode_from_reader(reader.get_metadata()?)?, + public_share: reader.get_public_share()?.to_vec(), + prep_share: VdafPrepShare::get_decoded_with_param( + &prep_state, + reader.get_prep_share()?, + ) + .map_err(to_capnp)?, + prep_state, + peer_prep_share: reader.get_peer_prep_share()?.to_vec().into(), + }) + } + initialized_report::Which::Rejected(reader) => { + Ok(InitializedReport::Rejected { + metadata: <_>::decode_from_reader(reader.get_metadata()?)?, + report_err: reader.get_failure()?.into(), + }) + } + }) + .collect::>()?, + vdaf, + }) + } +} + +impl From for initialized_report::ReportError { + fn from(failure: messages::ReportError) -> Self { + match failure { + messages::ReportError::Reserved => Self::Reserved, + messages::ReportError::BatchCollected => Self::BatchCollected, + messages::ReportError::ReportReplayed => Self::ReportReplayed, + messages::ReportError::ReportDropped => Self::ReportDropped, + messages::ReportError::HpkeUnknownConfigId => Self::HpkeUnknownConfigId, + messages::ReportError::HpkeDecryptError => Self::HpkeDecryptError, + messages::ReportError::VdafPrepError => Self::VdafPrepError, + messages::ReportError::BatchSaturated => Self::BatchSaturated, + messages::ReportError::TaskExpired => Self::TaskExpired, + messages::ReportError::InvalidMessage => Self::InvalidMessage, + messages::ReportError::ReportTooEarly => Self::ReportTooEarly, + messages::ReportError::TaskNotStarted => Self::TaskNotStarted, + } + } +} + +impl From for messages::ReportError { + fn from(val: initialized_report::ReportError) -> Self { + match val { + initialized_report::ReportError::Reserved => Self::Reserved, + initialized_report::ReportError::BatchCollected => Self::BatchCollected, + initialized_report::ReportError::ReportReplayed => Self::ReportReplayed, + initialized_report::ReportError::ReportDropped => Self::ReportDropped, + initialized_report::ReportError::HpkeUnknownConfigId => Self::HpkeUnknownConfigId, + initialized_report::ReportError::HpkeDecryptError => Self::HpkeDecryptError, + initialized_report::ReportError::VdafPrepError => Self::VdafPrepError, + initialized_report::ReportError::BatchSaturated => Self::BatchSaturated, + initialized_report::ReportError::TaskExpired => Self::TaskExpired, + initialized_report::ReportError::InvalidMessage => Self::InvalidMessage, + initialized_report::ReportError::ReportTooEarly => Self::ReportTooEarly, + initialized_report::ReportError::TaskNotStarted => Self::TaskNotStarted, + } + } +} + +fn to_capnp(e: E) -> capnp::Error { + capnp::Error { + kind: capnp::ErrorKind::Failed, + extra: e.to_string(), + } +} diff --git a/crates/daphne-service-utils/src/lib.rs b/crates/daphne-service-utils/src/lib.rs index c31aabad0..cc255864b 100644 --- a/crates/daphne-service-utils/src/lib.rs +++ b/crates/daphne-service-utils/src/lib.rs @@ -4,8 +4,10 @@ #![cfg_attr(not(test), deny(unused_crate_dependencies))] pub mod bearer_token; -#[cfg(feature = "durable_requests")] +#[cfg(any(feature = "durable_requests", feature = "compute-offload"))] pub mod capnproto; +#[cfg(feature = "compute-offload")] +pub mod compute_offload; #[cfg(feature = "durable_requests")] pub mod durable_requests; pub mod http_headers; @@ -13,7 +15,7 @@ pub mod http_headers; pub mod test_route_types; // the generated code expects this module to be defined at the root of the library. -#[cfg(feature = "durable_requests")] +#[cfg(any(feature = "durable_requests", feature = "compute-offload"))] #[doc(hidden)] pub mod base_capnp { #![allow(dead_code)] @@ -43,3 +45,14 @@ mod aggregation_job_store_capnp { "/src/durable_requests/bindings/aggregation_job_store_capnp.rs" )); } + +#[cfg(feature = "compute-offload")] +mod compute_offload_capnp { + #![allow(dead_code)] + #![allow(clippy::pedantic)] + #![allow(clippy::needless_lifetimes)] + include!(concat!( + env!("OUT_DIR"), + "/src/compute_offload/compute_offload_capnp.rs" + )); +} diff --git a/crates/daphne-worker-test/Cargo.toml b/crates/daphne-worker-test/Cargo.toml index 7145bc79e..f29750c78 100644 --- a/crates/daphne-worker-test/Cargo.toml +++ b/crates/daphne-worker-test/Cargo.toml @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Cloudflare, Inc. All rights reserved. +# Copyright (c) 2025 Cloudflare, Inc. All rights reserved. # SPDX-License-Identifier: BSD-3-Clause [package] @@ -18,10 +18,12 @@ crate-type = ["cdylib", "rlib"] default = ["console_error_panic_hook"] [dependencies] +async-trait.workspace = true cap.workspace = true cfg-if.workspace = true console_error_panic_hook = { version = "0.1.7", optional = true } daphne-worker = { path = "../daphne-worker", features = ["test-utils"] } +futures.workspace = true prometheus.workspace = true tracing.workspace = true worker.workspace = true diff --git a/crates/daphne-worker-test/docker/aggregator.Dockerfile b/crates/daphne-worker-test/docker/aggregator.Dockerfile index ebc462d9e..fdb1534d5 100644 --- a/crates/daphne-worker-test/docker/aggregator.Dockerfile +++ b/crates/daphne-worker-test/docker/aggregator.Dockerfile @@ -34,4 +34,4 @@ COPY crates/daphne-worker-test/wrangler.aggregator.toml / # this container doesn't need worker-build but the wrangler.toml requires it, so we just fake it RUN ln -s /usr/bin/true /usr/bin/worker-build -ENTRYPOINT ["wrangler", "dev", "--config", "wrangler.aggregator.toml", "-e", "helper", "--port", "8788"] +ENTRYPOINT ["wrangler", "dev", "--config", "wrangler.aggregator.toml", "-e", "helper", "--port", "8788", "--var", "COMPUTE_OFFLOAD_HOST:compute-offload:5000"] diff --git a/crates/daphne-worker-test/docker/docker-compose-e2e.yaml b/crates/daphne-worker-test/docker/docker-compose-e2e.yaml index c8f6a545e..65f9129ec 100644 --- a/crates/daphne-worker-test/docker/docker-compose-e2e.yaml +++ b/crates/daphne-worker-test/docker/docker-compose-e2e.yaml @@ -8,6 +8,17 @@ networks: driver: bridge services: + compute-offload: + networks: + - dap_network + ports: + - "4000" + build: + context: ../../.. + dockerfile: crates/daphne-server/docker/example-service.Dockerfile + target: compute-offload + environment: + - RUST_LOG=info leader: networks: - dap_network diff --git a/crates/daphne-worker-test/src/lib.rs b/crates/daphne-worker-test/src/lib.rs index dc1456a68..a48da5f3d 100644 --- a/crates/daphne-worker-test/src/lib.rs +++ b/crates/daphne-worker-test/src/lib.rs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: BSD-3-Clause use daphne_worker::{aggregator::App, initialize_tracing}; +use futures::stream; +use std::convert::Infallible; use tracing::info; -use worker::{event, Env, HttpRequest}; +use worker::{event, Env, HttpRequest, ResponseBody}; mod durable; mod utils; @@ -37,8 +39,12 @@ pub async fn main( daphne_worker::storage_proxy::handle_request(req, env, ®istry).await } Some("aggregator") => { + let host = env + .var("COMPUTE_OFFLOAD_HOST") + .map_or_else(|_| "localhost:5000".into(), |t| t.to_string()); + daphne_worker::aggregator::handle_dap_request( - App::new(env, ®istry, None).unwrap(), + App::new(env, ®istry, None, Box::new(ComputeOffload { host })).unwrap(), req, ) .await @@ -52,3 +58,41 @@ pub async fn main( Ok(response) } + +struct ComputeOffload { + host: String, +} + +#[async_trait::async_trait(?Send)] +impl daphne_worker::aggregator::ComputeOffload for ComputeOffload { + async fn request( + &self, + path: &str, + body: &[u8], + ) -> worker::Result> { + let response = worker::Fetch::Request( + worker::Request::new_with_init( + &format!("http://{}{path}", self.host), + &worker::RequestInit { + body: Some(worker::js_sys::Uint8Array::from(body).into()), + method: worker::Method::Post, + ..Default::default() + }, + ) + .unwrap(), + ) + .send() + .await?; + + Ok(daphne_worker::Response::builder() + .status(response.status_code()) + .body(match response.into_parts().1 { + ResponseBody::Empty => worker::Body::empty(), + ResponseBody::Body(vec) => { + worker::Body::from_stream(stream::iter([Ok::<_, Infallible>(vec)])).unwrap() + } + ResponseBody::Stream(readable_stream) => worker::Body::new(readable_stream), + }) + .unwrap()) + } +} diff --git a/crates/daphne-worker/Cargo.toml b/crates/daphne-worker/Cargo.toml index b09facb9b..da77cbca5 100644 --- a/crates/daphne-worker/Cargo.toml +++ b/crates/daphne-worker/Cargo.toml @@ -44,7 +44,7 @@ serde_json.workspace = true static_assertions.workspace = true thiserror.workspace = true tower-service.workspace = true -tower.workspace = true +tower = { workspace = true, features = ["util"] } tracing-core.workspace = true tracing-subscriber = { workspace = true, features = ["env-filter", "json"]} tracing.workspace = true @@ -57,7 +57,7 @@ features = ["query", "json", "http1", "http2"] [dependencies.daphne-service-utils] path = "../daphne-service-utils" -features = ["durable_requests"] +features = ["durable_requests", "compute-offload"] [dev-dependencies] daphne = { path = "../daphne", features = ["test-utils"] } diff --git a/crates/daphne-worker/src/aggregator/mod.rs b/crates/daphne-worker/src/aggregator/mod.rs index fb6fc4228..1e0254112 100644 --- a/crates/daphne-worker/src/aggregator/mod.rs +++ b/crates/daphne-worker/src/aggregator/mod.rs @@ -7,6 +7,7 @@ mod roles; mod router; use crate::storage::{kv, Do, Kv}; +use axum::response::Response; use config::{DaphneServiceConfig, PeerBearerToken}; use daphne::{ audit_log::{AuditLog, NoopAuditLog}, @@ -16,7 +17,13 @@ use daphne::{ roles::{leader::in_memory_leader::InMemoryLeaderState, DapAggregator as _}, DapError, }; -use daphne_service_utils::bearer_token::BearerToken; +use daphne_service_utils::{ + bearer_token::BearerToken, + capnproto::{ + CapnprotoPayloadDecode, CapnprotoPayloadDecodeExt, CapnprotoPayloadEncode, + CapnprotoPayloadEncodeExt, + }, +}; use either::Either::{self, Left, Right}; use metrics::DaphneServiceMetrics; use roles::BearerTokens; @@ -26,6 +33,37 @@ use worker::send::SendWrapper; pub use router::handle_dap_request; +#[async_trait::async_trait(?Send)] +pub trait ComputeOffload { + async fn request(&self, path: &str, body: &[u8]) -> worker::Result>; +} + +impl dyn ComputeOffload + Send + Sync { + pub async fn compute(&self, path: &str, body: &I) -> worker::Result + where + I: CapnprotoPayloadEncode, + O: CapnprotoPayloadDecode, + { + let resp = self.request(path, &body.encode_to_bytes()).await?; + + if resp.status().is_success() { + O::decode_from_bytes( + &http_body_util::BodyExt::collect(resp.into_body()) + .await? + .to_bytes(), + ) + .map_err(|e| { + worker::Error::RustError(format!("failed to decode body from cpu offload: {e:?}")) + }) + } else { + Err(worker::Error::RustError(format!( + "request to cpu offload failed with code: {}", + resp.status() + ))) + } + } +} + pub struct App { http: reqwest::Client, env: SendWrapper, @@ -34,6 +72,8 @@ pub struct App { service_config: DaphneServiceConfig, audit_log: Box, + compute_offload: Box, + /// Volatile memory for the Leader, including the work queue, pending reports, and pending /// colleciton requests. Note that in a production Leader, it is necessary to store this state /// across requsets. @@ -125,6 +165,7 @@ impl App { env: worker::Env, registry: &prometheus::Registry, audit_log: impl Into>>, + compute_offload: Box, ) -> Result { static PERSISTENT_ENOUGH_STATE: LazyLock>> = LazyLock::new(Default::default); @@ -138,6 +179,7 @@ impl App { audit_log: audit_log.into().unwrap_or_else(|| Box::new(NoopAuditLog)), service_config, test_leader_state: PERSISTENT_ENOUGH_STATE.clone(), + compute_offload, }) } diff --git a/crates/daphne-worker/src/aggregator/roles/aggregator.rs b/crates/daphne-worker/src/aggregator/roles/aggregator.rs index 7ffc4e938..cbe3ae3bb 100644 --- a/crates/daphne-worker/src/aggregator/roles/aggregator.rs +++ b/crates/daphne-worker/src/aggregator/roles/aggregator.rs @@ -356,6 +356,12 @@ impl DapAggregator for App { pub struct HpkeDecrypter(Marc>); +impl AsRef<[HpkeReceiverConfig]> for HpkeDecrypter { + fn as_ref(&self) -> &[HpkeReceiverConfig] { + self.0.as_ref() + } +} + impl hpke::HpkeDecrypter for HpkeDecrypter { fn hpke_decrypt( &self, diff --git a/crates/daphne-worker/src/aggregator/roles/helper.rs b/crates/daphne-worker/src/aggregator/roles/helper.rs index 2de552deb..26e284b49 100644 --- a/crates/daphne-worker/src/aggregator/roles/helper.rs +++ b/crates/daphne-worker/src/aggregator/roles/helper.rs @@ -14,12 +14,12 @@ use std::borrow::Cow; #[axum::async_trait] impl DapHelper for App { - async fn assert_agg_job_is_immutable( + async fn assert_agg_job_is_legal( &self, id: AggregationJobId, version: DapVersion, task_id: &TaskId, - req: &AggregationJobRequestHash, + req_hash: &AggregationJobRequestHash, ) -> Result<(), DapError> { let response = self .durable() @@ -27,7 +27,7 @@ impl DapHelper for App { .request(aggregation_job_store::Command::NewJob, (version, task_id)) .encode(&aggregation_job_store::NewJobRequest { id, - agg_job_hash: Cow::Borrowed(req.get()), + agg_job_hash: Cow::Borrowed(req_hash.get()), }) .send::() .await diff --git a/crates/daphne-worker/src/aggregator/router/helper.rs b/crates/daphne-worker/src/aggregator/router/helper.rs index a58e2a653..65ae20abc 100644 --- a/crates/daphne-worker/src/aggregator/router/helper.rs +++ b/crates/daphne-worker/src/aggregator/router/helper.rs @@ -1,26 +1,29 @@ // Copyright (c) 2025 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause -use std::sync::Arc; - +use super::{ + super::roles::fetch_replay_protection_override, extractor::dap_sender::FROM_LEADER, App, + AxumDapResponse, DapRequestExtractor, DaphneService, +}; +use crate::elapsed; use axum::{ extract::State, routing::{post, put}, }; use daphne::{ + fatal_error, + hpke::HpkeProvider, messages::AggregateShareReq, roles::{ helper::{self, HashedAggregationJobReq}, - DapHelper, + DapAggregator, DapHelper, }, + DapError, DapResponse, }; +use daphne_service_utils::compute_offload; use http::StatusCode; - -use super::{ - super::roles::fetch_replay_protection_override, extractor::dap_sender::FROM_LEADER, App, - AxumDapResponse, DapRequestExtractor, DaphneService, -}; -use crate::elapsed; +use prio::codec::ParameterizedEncode; +use std::{borrow::Cow, sync::Arc}; pub(super) fn add_helper_routes(router: super::Router) -> super::Router { router @@ -45,19 +48,58 @@ async fn agg_job( DapRequestExtractor(req): DapRequestExtractor, ) -> AxumDapResponse { let now = worker::Date::now(); + let version = req.version; - let resp = helper::handle_agg_job_init_req( - &*app, - req, - fetch_replay_protection_override(app.kv()).await, - ) + let agg_job_resp = async { + let (transition, req) = helper::handle_agg_job::start(req) + .check_aggregation_job_legality(&*app) + .await? + .resolve_task_config(&*app) + .await? + .into_parts(fetch_replay_protection_override(app.kv()).await)?; + + let hpke_receiver_configs = app.get_hpke_receiver_configs(req.version).await?; + + let initialized_reports: compute_offload::InitializedReports = app + .compute_offload + .compute( + "/compute_offload/initialize_reports", + &compute_offload::InitializeReports { + hpke_keys: Cow::Borrowed(hpke_receiver_configs.as_ref()), + valid_report_range: app.valid_report_time_range(), + task_id: req.task_id, + task_config: (&transition.task_config).into(), + agg_param: Cow::Borrowed(&req.payload.agg_param), + prep_inits: req.payload.prep_inits, + }, + ) + .await + .map_err(|e| fatal_error!(err = ?e, "failed to offload report initialization"))?; + + transition + .with_initialized_reports(initialized_reports.reports) + .finish_and_aggregate(&*app) + .await + } .await; let elapsed = elapsed(&now); app.server_metrics().aggregate_job_latency(elapsed); - AxumDapResponse::from_result_with_success_code(resp, app.server_metrics(), StatusCode::CREATED) + AxumDapResponse::from_result_with_success_code( + agg_job_resp.and_then(|agg_job_resp| { + Ok(DapResponse { + version, + media_type: daphne::constants::DapMediaType::AggregationJobResp, + payload: agg_job_resp + .get_encoded_with_param(&version) + .map_err(DapError::encoding)?, + }) + }), + app.server_metrics(), + StatusCode::CREATED, + ) } #[tracing::instrument( diff --git a/crates/daphne/src/error/aborts.rs b/crates/daphne/src/error/aborts.rs index 6ffede1c6..c560e4757 100644 --- a/crates/daphne/src/error/aborts.rs +++ b/crates/daphne/src/error/aborts.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Cloudflare, Inc. All rights reserved. +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause //! Definitions and tooling for DAP protocol aborts. @@ -18,7 +18,7 @@ use super::FatalDapError; // The display implementation of this error is used for metrics, as such, it can't be changed to // include field values /// DAP aborts. -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)] pub enum DapAbort { /// Bad request. Sent in response to an HTTP request that couldn't be handled preoprly. #[error("bad request")] diff --git a/crates/daphne/src/error/mod.rs b/crates/daphne/src/error/mod.rs index 15c72d676..4b802fec3 100644 --- a/crates/daphne/src/error/mod.rs +++ b/crates/daphne/src/error/mod.rs @@ -1,18 +1,17 @@ -// Copyright (c) 2023 Cloudflare, Inc. All rights reserved. +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause pub mod aborts; -use std::fmt::{Debug, Display}; - use crate::{messages::ReportError, vdaf::VdafError}; pub use aborts::DapAbort; +use aborts::ProblemDetails; use prio::codec::CodecError; - -use self::aborts::ProblemDetails; +use serde::{Deserialize, Serialize}; +use std::fmt::{Debug, Display}; /// DAP errors. -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)] pub enum DapError { /// Fatal error. If this triggers an abort, then treat this as an internal error. /// @@ -54,7 +53,8 @@ impl DapError { } } -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(transparent)] pub struct FatalDapError(pub(crate) String); impl FatalDapError { diff --git a/crates/daphne/src/hpke.rs b/crates/daphne/src/hpke.rs index 4d770dde7..2e3c8535e 100644 --- a/crates/daphne/src/hpke.rs +++ b/crates/daphne/src/hpke.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Cloudflare, Inc. All rights reserved. +// Copyright (c) 2025 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause //! Hybrid Public-Key Encryption ([HPKE](https://datatracker.ietf.org/doc/rfc9180/)). @@ -325,7 +325,7 @@ impl HpkeDecrypter for HpkeReceiverConfig { pub struct HpkeReceiverConfig { pub config: HpkeConfig, #[serde(with = "HpkePrivateKeySerde")] - private_key: HpkePrivateKey, + pub private_key: HpkePrivateKey, } #[cfg(any(test, feature = "test-utils"))] diff --git a/crates/daphne/src/protocol/report_init.rs b/crates/daphne/src/protocol/report_init.rs index 650e621f2..82adf2945 100644 --- a/crates/daphne/src/protocol/report_init.rs +++ b/crates/daphne/src/protocol/report_init.rs @@ -104,7 +104,7 @@ impl<'s> From<&'s DapTaskConfig> for PartialDapTaskConfigForReportInit<'s> { method_is_taskprov: config.method_is_taskprov(), version: config.version, vdaf: Cow::Borrowed(&config.vdaf), - vdaf_verify_key: Cow::Borrowed(&config.vdaf_verify_key), + vdaf_verify_key: config.vdaf_verify_key.clone(), } } } @@ -116,7 +116,7 @@ impl<'s> From<&'s PartialDapTaskConfigForReportInit<'_>> for PartialDapTaskConfi method_is_taskprov: config.method_is_taskprov, version: config.version, vdaf: Cow::Borrowed(&config.vdaf), - vdaf_verify_key: Cow::Borrowed(&config.vdaf_verify_key), + vdaf_verify_key: config.vdaf_verify_key.clone(), } } } @@ -126,7 +126,7 @@ pub struct PartialDapTaskConfigForReportInit<'s> { pub method_is_taskprov: bool, pub version: DapVersion, pub vdaf: Cow<'s, VdafConfig>, - pub vdaf_verify_key: Cow<'s, VdafVerifyKey>, + pub vdaf_verify_key: VdafVerifyKey, } impl

InitializedReport

{ diff --git a/crates/daphne/src/roles/helper/handle_agg_job.rs b/crates/daphne/src/roles/helper/handle_agg_job.rs index ebcda395e..699abe45c 100644 --- a/crates/daphne/src/roles/helper/handle_agg_job.rs +++ b/crates/daphne/src/roles/helper/handle_agg_job.rs @@ -82,7 +82,7 @@ impl HandleAggJob { ) -> Result, DapError> { let Self { state: Init(req) } = self; aggregator - .assert_agg_job_is_immutable( + .assert_agg_job_is_legal( req.resource_id, req.version, &req.task_id, diff --git a/crates/daphne/src/roles/helper/mod.rs b/crates/daphne/src/roles/helper/mod.rs index cebedec4e..2ae938bae 100644 --- a/crates/daphne/src/roles/helper/mod.rs +++ b/crates/daphne/src/roles/helper/mod.rs @@ -91,12 +91,12 @@ pub trait DapHelper: DapAggregator { /// - this the first time we see this aggregation job /// - this aggregation job has been seen before and it hasn't changed since the last time we /// saw it. - async fn assert_agg_job_is_immutable( + async fn assert_agg_job_is_legal( &self, id: AggregationJobId, version: DapVersion, task_id: &TaskId, - req: &AggregationJobRequestHash, + req_hash: &AggregationJobRequestHash, ) -> Result<(), DapError>; } diff --git a/crates/daphne/src/testing/mod.rs b/crates/daphne/src/testing/mod.rs index 94b193b5a..dd6d3df60 100644 --- a/crates/daphne/src/testing/mod.rs +++ b/crates/daphne/src/testing/mod.rs @@ -874,16 +874,16 @@ impl DapAggregator for InMemoryAggregator { #[async_trait] impl DapHelper for InMemoryAggregator { - async fn assert_agg_job_is_immutable( + async fn assert_agg_job_is_legal( &self, id: AggregationJobId, _version: DapVersion, _task_id: &TaskId, - req: &AggregationJobRequestHash, + req_hash: &AggregationJobRequestHash, ) -> Result<(), DapError> { match self.processed_jobs.lock().unwrap().entry(id) { Entry::Occupied(occupied_entry) => { - if occupied_entry.get() == req { + if occupied_entry.get() == req_hash { Ok(()) } else { Err(DapAbort::BadRequest( @@ -893,7 +893,7 @@ impl DapHelper for InMemoryAggregator { } } Entry::Vacant(vacant_entry) => { - vacant_entry.insert(req.clone()); + vacant_entry.insert(req_hash.clone()); Ok(()) } } diff --git a/crates/daphne/src/vdaf/mod.rs b/crates/daphne/src/vdaf/mod.rs index 3c66c00a5..adb190aa7 100644 --- a/crates/daphne/src/vdaf/mod.rs +++ b/crates/daphne/src/vdaf/mod.rs @@ -396,6 +396,18 @@ impl KeyType for VdafVerifyKey { } } +impl From<[u8; 32]> for VdafVerifyKey { + fn from(a: [u8; 32]) -> Self { + Self(a) + } +} + +impl VdafVerifyKey { + pub fn inner(&self) -> &[u8; 32] { + &self.0 + } +} + impl AsRef<[u8]> for VdafVerifyKey { fn as_ref(&self) -> &[u8] { &self.0