diff --git a/Cargo.lock b/Cargo.lock index a9b8c4b68..7d4dc8cdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1471,6 +1471,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "either" version = "1.12.0" @@ -1517,6 +1529,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -2546,7 +2578,7 @@ dependencies = [ "console-subscriber", "deadpool", "deadpool-postgres", - "derivative", + "educe", "fixed", "futures", "hex", @@ -2625,7 +2657,7 @@ dependencies = [ "assert_matches", "async-trait", "base64 0.22.1", - "derivative", + "educe", "futures", "git-version", "janus_aggregator_core", @@ -2664,7 +2696,7 @@ dependencies = [ "clap", "deadpool", "deadpool-postgres", - "derivative", + "educe", "futures", "hex", "http", @@ -2711,7 +2743,7 @@ dependencies = [ "assert_matches", "backoff", "bhttp", - "derivative", + "educe", "hex-literal", "http", "itertools 0.13.0", @@ -2738,7 +2770,7 @@ dependencies = [ "backoff", "base64 0.22.1", "chrono", - "derivative", + "educe", "fixed", "hpke-dispatch", "janus_collector", @@ -2768,7 +2800,7 @@ dependencies = [ "bytes", "chrono", "clap", - "derivative", + "educe", "fixed", "futures", "hex", @@ -2816,8 +2848,8 @@ dependencies = [ "base64 0.22.1", "chrono", "clap", - "derivative", "divviup-client", + "educe", "futures", "hex", "http", @@ -2860,7 +2892,7 @@ dependencies = [ "backoff", "base64 0.22.1", "clap", - "derivative", + "educe", "fixed", "futures", "hex", @@ -2916,7 +2948,7 @@ dependencies = [ "anyhow", "assert_matches", "base64 0.22.1", - "derivative", + "educe", "hex", "num_enum", "pretty_assertions", @@ -2937,7 +2969,6 @@ dependencies = [ "base64 0.22.1", "cfg-if", "clap", - "derivative", "fixed", "janus_collector", "janus_core", diff --git a/Cargo.toml b/Cargo.toml index 2faa10003..4ccde0dbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,8 @@ clap = { version = "4.5.21", features = ["cargo", "derive", "env"] } console-subscriber = "0.4.1" deadpool = "0.12.1" deadpool-postgres = "0.14.0" -derivative = "2.2.0" divviup-client = "0.4" +educe = { version = "0.6.0", default-features = false, features = ["Debug"] } fixed = "1.28" futures = "0.3.31" git-version = "0.3.9" diff --git a/aggregator/Cargo.toml b/aggregator/Cargo.toml index 02e6a6977..4885cc901 100644 --- a/aggregator/Cargo.toml +++ b/aggregator/Cargo.toml @@ -48,7 +48,7 @@ clap.workspace = true console-subscriber = { workspace = true, optional = true } deadpool = { workspace = true, features = ["rt_tokio_1"] } deadpool-postgres = { workspace = true } -derivative.workspace = true +educe.workspace = true fixed = { workspace = true, optional = true } futures = { workspace = true } hex = { workspace = true, features = ["serde"] } diff --git a/aggregator/src/aggregator/aggregation_job_driver.rs b/aggregator/src/aggregator/aggregation_job_driver.rs index 732f1956b..2451dd3de 100644 --- a/aggregator/src/aggregator/aggregation_job_driver.rs +++ b/aggregator/src/aggregator/aggregation_job_driver.rs @@ -16,7 +16,7 @@ use crate::{ use anyhow::{anyhow, Result}; use backoff::backoff::Backoff; use bytes::Bytes; -use derivative::Derivative; +use educe::Educe; use futures::future::BoxFuture; use janus_aggregator_core::{ datastore::{ @@ -58,8 +58,8 @@ use tracing::{debug, error, info, info_span, trace_span, warn, Span}; #[cfg(test)] mod tests; -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub struct AggregationJobDriver { // Configuration. batch_aggregation_shard_count: u64, @@ -69,17 +69,17 @@ pub struct AggregationJobDriver { http_client: reqwest::Client, backoff: B, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_success_counter: Counter, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregate_step_failure_counter: Counter, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregated_report_share_dimension_histogram: Histogram, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] job_cancel_counter: Counter, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] job_retry_counter: Counter, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] http_request_duration_histogram: Histogram, } diff --git a/aggregator/src/aggregator/collection_job_driver.rs b/aggregator/src/aggregator/collection_job_driver.rs index 8eeeb8541..0c960f657 100644 --- a/aggregator/src/aggregator/collection_job_driver.rs +++ b/aggregator/src/aggregator/collection_job_driver.rs @@ -8,7 +8,7 @@ use crate::aggregator::{ use anyhow::bail; use backoff::backoff::Backoff; use bytes::Bytes; -use derivative::Derivative; +use educe::Educe; use futures::future::{try_join_all, BoxFuture}; use janus_aggregator_core::{ datastore::{ @@ -42,13 +42,13 @@ use tokio::try_join; use tracing::{error, info, warn}; /// Drives a collection job. -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub struct CollectionJobDriver { // Dependencies. http_client: reqwest::Client, backoff: B, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] metrics: CollectionJobDriverMetrics, // Configuration. diff --git a/aggregator/src/aggregator/key_rotator.rs b/aggregator/src/aggregator/key_rotator.rs index 9fdd28667..8444e90aa 100644 --- a/aggregator/src/aggregator/key_rotator.rs +++ b/aggregator/src/aggregator/key_rotator.rs @@ -7,7 +7,7 @@ use std::{ use crate::aggregator::Config as AggregatorConfig; // used in doccomment. use crate::cache::GlobalHpkeKeypairCache; use anyhow::{anyhow, Error}; -use derivative::Derivative; +use educe::Educe; use futures::{future::try_join_all, FutureExt}; use janus_aggregator_core::datastore::{ models::{GlobalHpkeKeypair, HpkeKeyState}, @@ -155,14 +155,14 @@ fn duration_since(clock: &C, time: &Time) -> Duration { } /// In-memory representation of the `global_hpke_keys` table. -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] struct HpkeKeyRotator<'a, C: Clock> { clock: C, config: &'a HpkeKeyRotatorConfig, // Data structures for intermediate state. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] available_ids: Box + Send + Sync>, keypairs: HashMap, initially_empty: bool, diff --git a/aggregator/src/binaries/aggregator.rs b/aggregator/src/binaries/aggregator.rs index 20cbf141a..69fa9730c 100644 --- a/aggregator/src/binaries/aggregator.rs +++ b/aggregator/src/binaries/aggregator.rs @@ -14,7 +14,7 @@ use crate::{ }; use anyhow::{anyhow, Context, Result}; use clap::Parser; -use derivative::Derivative; +use educe::Educe; use janus_aggregator_api::{self, aggregator_api_handler}; use janus_aggregator_core::datastore::Datastore; use janus_core::{auth_tokens::AuthenticationToken, time::RealClock, TokioRuntime}; @@ -240,9 +240,9 @@ impl BinaryOptions for Options { } /// Options for serving the aggregator API. -#[derive(Clone, Derivative, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Educe, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -#[derivative(Debug)] +#[educe(Debug)] pub struct AggregatorApi { /// Address on which this server should listen for connections to the Janus aggregator API /// and serve its API endpoints, independently from the address on which the DAP API is @@ -256,7 +256,7 @@ pub struct AggregatorApi { pub path_prefix: Option, /// Resource location at which the DAP service managed by this aggregator api can be found /// on the public internet. Required. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub public_dap_url: Url, } diff --git a/aggregator/src/config.rs b/aggregator/src/config.rs index e126624e9..3520440e0 100644 --- a/aggregator/src/config.rs +++ b/aggregator/src/config.rs @@ -2,7 +2,7 @@ use crate::{metrics::MetricsConfiguration, trace::TraceConfiguration}; use backoff::{ExponentialBackoff, ExponentialBackoffBuilder}; -use derivative::Derivative; +use educe::Educe; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{ fmt::Debug, @@ -77,12 +77,12 @@ pub trait BinaryConfig: Debug + DeserializeOwned { } /// Configuration for a Janus server using a database. -#[derive(Clone, Derivative, PartialEq, Eq, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq, Serialize, Deserialize)] +#[educe(Debug)] #[serde(deny_unknown_fields)] pub struct DbConfig { /// URL at which to connect to the database. - #[derivative(Debug(format_with = "format_database_url"))] + #[educe(Debug(method(format_database_url)))] pub url: Url, /// Timeout in seconds to apply when creating, waiting for, or recycling diff --git a/aggregator/src/diagnostic.rs b/aggregator/src/diagnostic.rs index 09ae5e377..522b7b113 100644 --- a/aggregator/src/diagnostic.rs +++ b/aggregator/src/diagnostic.rs @@ -1,15 +1,15 @@ //! Writing diagnostic files to disk. use anyhow::Context; -use derivative::Derivative; +use educe::Educe; use janus_messages::{AggregationJobId, ReportMetadata, TaskId}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{fs::File, path::Path, time::SystemTime}; use uuid::Uuid; /// Represents an illegal attempt to mutate an aggregation job. -#[derive(Derivative, Clone, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, Clone, Serialize, Deserialize)] +#[educe(Debug)] pub struct AggregationJobInitForbiddenMutationEvent { /// The ID of the task. #[serde(with = "serialize_task_id")] @@ -21,7 +21,7 @@ pub struct AggregationJobInitForbiddenMutationEvent { /// The SHA-256 of the request that created the aggregation job. #[serde(with = "serialize_hash_option")] - #[derivative(Debug(format_with = "fmt_hash_option"))] + #[educe(Debug(method(fmt_hash_option)))] pub original_request_hash: Option<[u8; 32]>, /// The ordered report metadatas from the request that created the aggregation job. @@ -36,7 +36,7 @@ pub struct AggregationJobInitForbiddenMutationEvent { /// The SHA-256 of the request that attempted to mutate the aggregation job. #[serde(with = "serialize_hash_option")] - #[derivative(Debug(format_with = "fmt_hash_option"))] + #[educe(Debug(method(fmt_hash_option)))] pub mutating_request_hash: Option<[u8; 32]>, /// The ordered report metadatas from the request that attempted to mutate the aggregation job. diff --git a/aggregator/src/metrics/tokio_runtime.rs b/aggregator/src/metrics/tokio_runtime.rs index 28d885701..4c6300ea0 100644 --- a/aggregator/src/metrics/tokio_runtime.rs +++ b/aggregator/src/metrics/tokio_runtime.rs @@ -2,7 +2,7 @@ use std::time::Duration; use std::time::SystemTime; -use derivative::Derivative; +use educe::Educe; use opentelemetry::{metrics::MetricsError, InstrumentationLibrary, KeyValue}; #[cfg(tokio_unstable)] use opentelemetry_sdk::metrics::data::{Histogram, HistogramDataPoint, Sum, Temporality}; @@ -62,20 +62,20 @@ pub(crate) fn configure_runtime( } } -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub(super) struct TokioRuntimeMetrics { runtime_metrics: RuntimeMetrics, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] scope: InstrumentationLibrary, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] start_time: SystemTime, num_workers: usize, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_global_queue: Vec, #[cfg(tokio_unstable)] @@ -83,26 +83,26 @@ pub(super) struct TokioRuntimeMetrics { } #[cfg(tokio_unstable)] -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] struct UnstableTokioRuntimeMetrics { poll_time_histogram_num_buckets: usize, poll_time_histogram_bucket_bounds: Vec, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_local: Vec, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_local_overflow: Vec, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_remote: Vec, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_local_queue_worker: Vec>, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] attributes_blocking_queue: Vec, } diff --git a/aggregator_api/Cargo.toml b/aggregator_api/Cargo.toml index 2ef2735cc..e834cd05d 100644 --- a/aggregator_api/Cargo.toml +++ b/aggregator_api/Cargo.toml @@ -12,7 +12,7 @@ version.workspace = true anyhow.workspace = true async-trait = { workspace = true } base64.workspace = true -derivative.workspace = true +educe.workspace = true git-version.workspace = true janus_aggregator_core.workspace = true janus_core.workspace = true diff --git a/aggregator_api/src/models.rs b/aggregator_api/src/models.rs index 8c250da41..0d7863cf9 100644 --- a/aggregator_api/src/models.rs +++ b/aggregator_api/src/models.rs @@ -1,5 +1,5 @@ use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use janus_aggregator_core::{ datastore::models::{ GlobalHpkeKeypair, HpkeKeyState, TaskAggregationCounter, TaskUploadCounter, @@ -27,11 +27,11 @@ pub(crate) enum AggregatorRole { Helper, } -#[derive(Serialize, PartialEq, Eq, Derivative)] -#[derivative(Debug)] +#[derive(Serialize, PartialEq, Eq, Educe)] +#[educe(Debug)] pub(crate) struct AggregatorApiConfig { pub protocol: &'static str, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub dap_url: Url, pub role: AggregatorRole, pub vdafs: Vec, @@ -58,12 +58,12 @@ pub(crate) struct GetTaskIdsResp { pub(crate) pagination_token: Option, } -#[derive(Derivative, PartialEq, Eq, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, PartialEq, Eq, Serialize, Deserialize)] +#[educe(Debug)] pub(crate) struct PostTaskReq { /// URL relative to which this task's peer aggregator's DAP API can be found. The peer /// aggregator plays the DAP role opposite to the one in the `role` field. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub(crate) peer_aggregator_endpoint: Url, /// DAP query type for this task. pub(crate) query_type: QueryType, @@ -100,14 +100,14 @@ pub(crate) struct PatchTaskReq { pub(crate) task_expiration: Option>, } -#[derive(Clone, Derivative, PartialEq, Eq, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq, Serialize, Deserialize)] +#[educe(Debug)] pub(crate) struct TaskResp { /// ID of the DAP Task. pub(crate) task_id: TaskId, /// URL relative to which this task's peer aggregator's DAP API can be found. The peer /// aggregator plays the DAP role opposite to the one in the `role` field. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub(crate) peer_aggregator_endpoint: Url, /// DAP query type for this task. pub(crate) query_type: QueryType, @@ -209,10 +209,10 @@ pub(crate) struct PatchGlobalHpkeConfigReq { pub(crate) state: HpkeKeyState, } -#[derive(Derivative, PartialEq, Eq, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, PartialEq, Eq, Serialize, Deserialize)] +#[educe(Debug)] pub(crate) struct TaskprovPeerAggregatorResp { - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub(crate) endpoint: Url, pub(crate) role: Role, pub(crate) collector_hpke_config: HpkeConfig, diff --git a/aggregator_core/Cargo.toml b/aggregator_core/Cargo.toml index 9157a6744..99156f9cf 100644 --- a/aggregator_core/Cargo.toml +++ b/aggregator_core/Cargo.toml @@ -30,7 +30,7 @@ chrono.workspace = true clap.workspace = true deadpool = { workspace = true, features = ["rt_tokio_1"] } deadpool-postgres = { workspace = true } -derivative.workspace = true +educe.workspace = true futures = { workspace = true } hex = { workspace = true, features = ["serde"], optional = true } http.workspace = true diff --git a/aggregator_core/src/datastore/models.rs b/aggregator_core/src/datastore/models.rs index effa70771..d6f65264a 100644 --- a/aggregator_core/src/datastore/models.rs +++ b/aggregator_core/src/datastore/models.rs @@ -4,7 +4,7 @@ use crate::{datastore::Error, task}; use base64::{display::Base64Display, engine::general_purpose::URL_SAFE_NO_PAD}; use chrono::NaiveDateTime; use clap::ValueEnum; -use derivative::Derivative; +use educe::Educe; use janus_core::{ auth_tokens::{AuthenticationToken, AuthenticationTokenHash}, hpke::{HpkeCiphersuite, HpkeKeypair}, @@ -98,20 +98,21 @@ impl From<&AuthenticationTokenHash> for AuthenticationTokenType { /// Represents a report as it is stored in the leader's database, corresponding to a row in /// `client_reports`, where `leader_input_share` and `helper_encrypted_input_share` are required /// to be populated. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub struct LeaderStoredReport where A: vdaf::Aggregator, { task_id: TaskId, metadata: ReportMetadata, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] public_share: A::PublicShare, + #[educe(Debug(ignore))] leader_extensions: Vec, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] leader_input_share: A::InputShare, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] helper_encrypted_input_share: HpkeCiphertext, } @@ -353,8 +354,8 @@ impl AggregatorRole { } /// AggregationJob represents an aggregation job from the DAP specification. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub struct AggregationJob> { /// The ID of the task this aggregation job belongs to. @@ -362,7 +363,7 @@ pub struct AggregationJob> { StartLeader { /// Public share for this report. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] public_share: A::PublicShare, /// The sequence of extensions from the Leader's input share for this report. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] leader_extensions: Vec, /// The Leader's input share for this report. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] leader_input_share: A::InputShare, /// The Helper's encrypted input share for this report. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] helper_encrypted_input_share: HpkeCiphertext, }, WaitingLeader { /// Most recent transition for this report aggregation. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] transition: PingPongTransition, }, WaitingHelper { /// Helper's current preparation state - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] prepare_state: A::PrepareState, }, Finished, @@ -1191,8 +1192,8 @@ impl ReportAggregationMetadata { /// `aggregation_parameter`. This is the finest-grained possible aggregate share we can emit for /// this task. The aggregate share constructed to service a collect or aggregate share request /// consists of one or more `BatchAggregation`s merged together. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub struct BatchAggregation< const SEED_SIZE: usize, Q: QueryType, @@ -1203,7 +1204,7 @@ pub struct BatchAggregation< /// The identifier of the batch being aggregated over. batch_identifier: Q::BatchIdentifier, /// The VDAF aggregation parameter used to prepare and accumulate input shares. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: A::AggregationParam, /// The index of this batch aggregation among all batch aggregations for /// this (task_id, batch_identifier, aggregation_parameter). @@ -1417,18 +1418,18 @@ where } /// Represents the state of a batch aggregation. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub enum BatchAggregationState> { Aggregating { /// The aggregate over all the input shares that have been prepared so far by this /// aggregator. Will only be None if there are no reports. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregate_share: Option, /// The number of reports currently included in this aggregate share. report_count: u64, /// Checksum over the aggregated report shares. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] checksum: ReportIdChecksum, /// The number of aggregation jobs that have been created for this batch. aggregation_jobs_created: u64, @@ -1439,12 +1440,12 @@ pub enum BatchAggregationState, /// The number of reports currently included in this aggregate share. report_count: u64, /// Checksum over the aggregated report shares. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] checksum: ReportIdChecksum, /// The number of aggregation jobs that have been created for this batch. aggregation_jobs_created: u64, @@ -1648,8 +1649,8 @@ where /// CollectionJob represents a row in the `collection_jobs` table, used by leaders to represent /// running collection jobs and store the results of completed ones. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub struct CollectionJob> { /// The task ID for this collection job. task_id: TaskId, @@ -1658,7 +1659,7 @@ pub struct CollectionJob, /// The VDAF aggregation parameter used to prepare and aggregate input shares. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: A::AggregationParam, /// The batch interval covered by the collection job. batch_identifier: Q::BatchIdentifier, @@ -1775,8 +1776,8 @@ where { } -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] pub enum CollectionJobState> { Start, Finished { @@ -1788,7 +1789,7 @@ pub enum CollectionJobState); +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] +pub struct SecretBytes(#[educe(Debug(ignore))] Vec); impl SecretBytes { pub fn new(buf: Vec) -> Self { diff --git a/aggregator_core/src/task.rs b/aggregator_core/src/task.rs index f1929f5b3..6b15be7c3 100644 --- a/aggregator_core/src/task.rs +++ b/aggregator_core/src/task.rs @@ -2,7 +2,7 @@ use crate::SecretBytes; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use janus_core::{ auth_tokens::{AuthenticationToken, AuthenticationTokenHash}, hpke::HpkeKeypair, @@ -82,9 +82,9 @@ impl TryFrom<&taskprov::Query> for QueryType { /// A verification key for a VDAF, with a fixed length. It must be kept secret from clients to /// maintain robustness, and it must be shared between aggregators. -#[derive(Derivative, Clone, Copy)] -#[derivative(Debug)] -pub struct VerifyKey(#[derivative(Debug = "ignore")] [u8; SEED_SIZE]); +#[derive(Educe, Clone, Copy)] +#[educe(Debug)] +pub struct VerifyKey(#[educe(Debug(ignore))] [u8; SEED_SIZE]); impl VerifyKey { pub fn new(array: [u8; SEED_SIZE]) -> VerifyKey { @@ -106,8 +106,7 @@ impl TryFrom<&SecretBytes> for VerifyKey { } /// Task parameters common to all views of a DAP task. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] struct CommonTaskParameters { /// Unique identifier for the task. task_id: TaskId, @@ -218,13 +217,13 @@ impl CommonTaskParameters { } /// An aggregator's view of the task's parameters. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub struct AggregatorTask { /// Common task parameters common_parameters: CommonTaskParameters, /// URL relative to which the peer aggregator's API endpoints are found. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] peer_aggregator_endpoint: Url, /// Parameters specific to either aggregator role aggregator_parameters: AggregatorTaskParameters, @@ -527,8 +526,8 @@ impl AggregatorTask { } /// Role-specific task parameters for the aggregator DAP roles. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub enum AggregatorTaskParameters { /// Task parameters held exclusively by the DAP leader. Leader { @@ -795,7 +794,7 @@ pub mod test_util { }, SecretBytes, }; - use derivative::Derivative; + use educe::Educe; use janus_core::{ auth_tokens::{AuthenticationToken, AuthenticationTokenHash}, hpke::HpkeKeypair, @@ -811,16 +810,16 @@ pub mod test_util { use url::Url; /// All parameters and secrets for a task, for all participants. - #[derive(Clone, Derivative, PartialEq, Eq)] - #[derivative(Debug)] + #[derive(Clone, Educe, PartialEq, Eq)] + #[educe(Debug)] pub struct Task { /// Common task parameters common_parameters: CommonTaskParameters, /// URL relative to which the leader aggregator's API endpoints are found. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] leader_aggregator_endpoint: Url, /// URL relative to which the leader aggregator's API endpoints are found. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] helper_aggregator_endpoint: Url, /// HPKE configuration and private key used by the collector to decrypt aggregate shares. collector_hpke_keypair: HpkeKeypair, diff --git a/aggregator_core/src/taskprov.rs b/aggregator_core/src/taskprov.rs index 94e5e1507..a6337ef1a 100644 --- a/aggregator_core/src/taskprov.rs +++ b/aggregator_core/src/taskprov.rs @@ -1,6 +1,6 @@ use crate::{task::Error, SecretBytes}; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use janus_core::{auth_tokens::AuthenticationToken, vdaf::VdafInstance}; use janus_messages::{Duration, HpkeConfig, Role, TaskId}; use rand::{distributions::Standard, prelude::Distribution}; @@ -12,9 +12,9 @@ use serde::{ use std::{fmt, str::FromStr, sync::OnceLock}; use url::Url; -#[derive(Derivative, Clone, Copy, PartialEq, Eq)] -#[derivative(Debug)] -pub struct VerifyKeyInit(#[derivative(Debug = "ignore")] [u8; Self::LEN]); +#[derive(Educe, Clone, Copy, PartialEq, Eq)] +#[educe(Debug)] +pub struct VerifyKeyInit(#[educe(Debug(ignore))] [u8; Self::LEN]); impl VerifyKeyInit { pub const LEN: usize = 32; @@ -92,12 +92,12 @@ impl FromStr for VerifyKeyInit { /// Represents another aggregator that is peered with our aggregator for taskprov purposes. Contains /// data that needs to be identical between both aggregators for the taskprov flow to work. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub struct PeerAggregator { /// The URL at which the peer aggregator can be reached. This, along with `role`, is used to /// uniquely represent the peer aggregator. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] endpoint: Url, /// The role that the peer aggregator takes in DAP. Must be [`Role::Leader`] or [`Role::Helper`]. diff --git a/client/Cargo.toml b/client/Cargo.toml index f9779ec64..82239b945 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -19,7 +19,7 @@ ohttp = ["dep:ohttp", "dep:bhttp"] [dependencies] backoff = { workspace = true, features = ["tokio"] } bhttp = { workspace = true, features = ["bhttp", "http"], optional = true } -derivative.workspace = true +educe.workspace = true http.workspace = true itertools.workspace = true janus_core.workspace = true diff --git a/client/src/lib.rs b/client/src/lib.rs index 4bbc33edc..c5fe8c9e2 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -42,7 +42,7 @@ use backoff::ExponentialBackoff; #[cfg(feature = "ohttp")] use bhttp::{ControlData, Message, Mode}; -use derivative::Derivative; +use educe::Educe; #[cfg(feature = "ohttp")] use http::{header::ACCEPT, HeaderValue}; use http::{header::CONTENT_TYPE, StatusCode}; @@ -135,16 +135,16 @@ const OHTTP_REQUEST_MEDIA_TYPE: &str = "message/ohttp-req"; const OHTTP_RESPONSE_MEDIA_TYPE: &str = "message/ohttp-res"; /// The DAP client's view of task parameters. -#[derive(Clone, Derivative)] -#[derivative(Debug)] +#[derive(Clone, Educe)] +#[educe(Debug)] struct ClientParameters { /// Unique identifier for the task. task_id: TaskId, /// URL relative to which the Leader's API endpoints are found. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] leader_aggregator_endpoint: Url, /// URL relative to which the Helper's API endpoints are found. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] helper_aggregator_endpoint: Url, /// The time precision of the task. This value is shared by all parties in the protocol, and is /// used to compute report timestamps. diff --git a/collector/Cargo.toml b/collector/Cargo.toml index 849bf6ffe..c06e1ab96 100644 --- a/collector/Cargo.toml +++ b/collector/Cargo.toml @@ -20,7 +20,7 @@ test-util = [] [dependencies] backoff = { workspace = true, features = ["tokio"] } chrono.workspace = true -derivative.workspace = true +educe.workspace = true fixed = { workspace = true, optional = true } hpke-dispatch = { workspace = true, features = ["serde"] } janus_core.workspace = true diff --git a/collector/src/lib.rs b/collector/src/lib.rs index bf5f68976..c22b34feb 100644 --- a/collector/src/lib.rs +++ b/collector/src/lib.rs @@ -67,7 +67,7 @@ use backoff::backoff::Backoff; pub use backoff::ExponentialBackoff; use chrono::{DateTime, Duration, TimeZone, Utc}; pub use credential::PrivateCollectorCredential; -use derivative::Derivative; +use educe::Educe; pub use janus_core::auth_tokens::AuthenticationToken; use janus_core::{ hpke::{self, HpkeApplicationInfo, HpkeKeypair}, @@ -159,8 +159,8 @@ pub fn default_http_client() -> Result { } /// Collector state related to a collection job that is in progress. -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub struct CollectionJob where Q: QueryType, @@ -170,7 +170,7 @@ where /// The collection request's query. query: Query, /// The aggregation parameter used in this collection request. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: P, } @@ -204,8 +204,8 @@ impl CollectionJob { } } -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] /// The result of a collection request poll operation. This will either provide the collection /// result or indicate that the collection is still being processed. pub enum PollResult @@ -213,7 +213,7 @@ where Q: QueryType, { /// The collection result from a completed collection request. - CollectionResult(#[derivative(Debug = "ignore")] Collection), + CollectionResult(#[educe(Debug(ignore))] Collection), /// The collection request is not yet ready. If present, the [`RetryAfter`] object is the time /// at which the leader recommends retrying the request. NotReady(Option), @@ -386,24 +386,24 @@ impl CollectorBuilder { } /// A DAP collector. -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub struct Collector { /// Unique identifier for the task. task_id: TaskId, /// The base URL of the leader's aggregator API endpoints. - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] leader_endpoint: Url, /// The authentication information needed to communicate with the leader aggregator. authentication: AuthenticationToken, /// HPKE keypair used for decryption of aggregate shares. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] hpke_keypair: HpkeKeypair, /// An implementation of the task's VDAF. vdaf: V, /// HTTPS client. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] http_client: reqwest::Client, /// Parameters to use when retrying HTTP requests. http_request_retry_parameters: ExponentialBackoff, diff --git a/core/Cargo.toml b/core/Cargo.toml index 31d4470fe..7a7c02dc2 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -40,7 +40,7 @@ base64.workspace = true bytes.workspace = true chrono = { workspace = true, features = ["clock"] } clap.workspace = true -derivative.workspace = true +educe.workspace = true fixed = { workspace = true, optional = true } futures = { workspace = true } hex = { workspace = true } diff --git a/core/src/auth_tokens.rs b/core/src/auth_tokens.rs index 2381db7e9..0b3940a6b 100644 --- a/core/src/auth_tokens.rs +++ b/core/src/auth_tokens.rs @@ -1,6 +1,6 @@ use anyhow::anyhow; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use http::{header::AUTHORIZATION, HeaderValue}; use rand::{distributions::Standard, prelude::Distribution}; use regex::Regex; @@ -19,8 +19,7 @@ pub const DAP_AUTH_HEADER: &str = "DAP-Auth-Token"; /// Different modes of authentication supported by Janus for either sending requests (e.g., leader /// to helper) or receiving them (e.g., collector to leader). -#[derive(Clone, Derivative, Serialize, Deserialize, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "type", content = "token")] #[non_exhaustive] pub enum AuthenticationToken { @@ -129,10 +128,10 @@ impl Distribution for Standard { /// /// This opaque type ensures it's impossible to construct an [`AuthenticationToken`] whose contents /// are invalid. -#[derive(Clone, Derivative, Serialize)] -#[derivative(Debug)] +#[derive(Clone, Educe, Serialize)] +#[educe(Debug)] #[serde(transparent)] -pub struct DapAuthToken(#[derivative(Debug = "ignore")] String); +pub struct DapAuthToken(#[educe(Debug(ignore))] String); impl DapAuthToken { /// Returns the token as a string. @@ -228,10 +227,10 @@ impl Distribution for Standard { /// /// This opaque type ensures it's impossible to construct an [`AuthenticationToken`] whose contents /// are invalid. -#[derive(Clone, Derivative, Serialize)] -#[derivative(Debug)] +#[derive(Clone, Educe, Serialize)] +#[educe(Debug)] #[serde(transparent)] -pub struct BearerToken(#[derivative(Debug = "ignore")] String); +pub struct BearerToken(#[educe(Debug(ignore))] String); impl BearerToken { /// Returns the token as a string. @@ -328,8 +327,8 @@ impl Distribution for Standard { /// The hash of an authentication token, which may be used to validate tokens in incoming requests /// but not to authenticate outgoing requests. -#[derive(Clone, Derivative, Deserialize, Serialize, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, Deserialize, Serialize, Eq)] +#[educe(Debug)] #[serde(tag = "type", content = "hash")] #[non_exhaustive] pub enum AuthenticationTokenHash { @@ -340,7 +339,7 @@ pub enum AuthenticationTokenHash { /// /// [1]: https://datatracker.ietf.org/doc/html/rfc6750#section-2.1 Bearer( - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] #[serde( serialize_with = "AuthenticationTokenHash::serialize_contents", deserialize_with = "AuthenticationTokenHash::deserialize_contents" @@ -357,7 +356,7 @@ pub enum AuthenticationTokenHash { /// [3]: https://datatracker.ietf.org/doc/html/draft-dcook-ppm-dap-interop-test-design-03#section-4.4.2 /// [4]: https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap-01#name-https-sender-authentication DapAuth( - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] #[serde( serialize_with = "AuthenticationTokenHash::serialize_contents", deserialize_with = "AuthenticationTokenHash::deserialize_contents" diff --git a/core/src/dp.rs b/core/src/dp.rs index 5c18aa7fd..ef9cfc2bf 100644 --- a/core/src/dp.rs +++ b/core/src/dp.rs @@ -1,4 +1,3 @@ -use derivative::Derivative; #[cfg(feature = "fpvec_bounded_l2")] use fixed::traits::Fixed; #[cfg(feature = "fpvec_bounded_l2")] @@ -34,7 +33,7 @@ impl DifferentialPrivacyDistribution for NoDistribution {} /// A "no-op" differential privacy strategy. Tasks which don't require differential privacy should /// use this type as their `DifferentialPrivacyStrategy`. -#[derive(Debug, Derivative, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct NoDifferentialPrivacy; impl DifferentialPrivacyStrategy for NoDifferentialPrivacy { type Budget = NoBudget; diff --git a/core/src/hpke.rs b/core/src/hpke.rs index 6a8590305..3b7b93bf7 100644 --- a/core/src/hpke.rs +++ b/core/src/hpke.rs @@ -1,6 +1,6 @@ //! Encryption and decryption of messages using HPKE (RFC 9180). use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use hpke_dispatch::{HpkeError, Kem, Keypair}; use janus_messages::{ HpkeAeadId, HpkeCiphertext, HpkeConfig, HpkeConfigId, HpkeKdfId, HpkeKemId, HpkePublicKey, Role, @@ -90,9 +90,9 @@ impl HpkeApplicationInfo { /// An HPKE private key, serialized using the `SerializePrivateKey` function as /// described in RFC 9180, §4 and §7.1.2. // TODO(#230): refactor HpkePrivateKey to simplify usage -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] -pub struct HpkePrivateKey(#[derivative(Debug = "ignore")] Vec); +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] +pub struct HpkePrivateKey(#[educe(Debug(ignore))] Vec); impl HpkePrivateKey { /// Construct a private key from its serialized form. diff --git a/core/src/vdaf.rs b/core/src/vdaf.rs index 6ee9dc376..ac70adbd2 100644 --- a/core/src/vdaf.rs +++ b/core/src/vdaf.rs @@ -1,4 +1,3 @@ -use derivative::Derivative; use janus_messages::taskprov; use prio::{ field::Field64, @@ -25,7 +24,7 @@ pub const VERIFY_KEY_LENGTH_HMACSHA256_AES128: usize = 32; /// Bitsize parameter for the `Prio3FixedPointBoundedL2VecSum` VDAF. #[cfg(feature = "fpvec_bounded_l2")] -#[derive(Debug, Derivative, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Prio3FixedPointBoundedL2VecSumBitSize { BitSize16, BitSize32, @@ -91,8 +90,7 @@ pub mod vdaf_dp_strategies { /// [draft-irtf-cfrg-vdaf-03][1] and implementations in [`prio::vdaf::prio3`]. /// /// [1]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/03/ -#[derive(Derivative, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[non_exhaustive] pub enum VdafInstance { /// A `Prio3` counter. diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 2a704a179..832cdf379 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -46,8 +46,8 @@ uuid.workspace = true [dev-dependencies] chrono.workspace = true -derivative.workspace = true divviup-client = { workspace = true, features = ["admin"] } +educe.workspace = true janus_collector = { workspace = true, features = ["test-util"] } opentelemetry.workspace = true quickcheck.workspace = true diff --git a/integration_tests/tests/integration/simulation/run.rs b/integration_tests/tests/integration/simulation/run.rs index 87d6e99c8..f69f330a4 100644 --- a/integration_tests/tests/integration/simulation/run.rs +++ b/integration_tests/tests/integration/simulation/run.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration as StdDuration, Instant}, }; -use derivative::Derivative; +use educe::Educe; use futures::future::join_all; use janus_aggregator::aggregator; use janus_aggregator_core::{ @@ -534,13 +534,13 @@ impl Simulation { } } -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Educe)] +#[educe(Debug)] pub(super) struct State { pub(super) stopper: Stopper, pub(super) clock: MockClock, pub(super) meter: Meter, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] pub(super) runtime_manager: TestRuntimeManager<&'static str>, pub(super) vdaf_instance: VdafInstance, pub(super) vdaf: Prio3Histogram, diff --git a/interop_binaries/Cargo.toml b/interop_binaries/Cargo.toml index 0da11098d..4e89acf1c 100644 --- a/interop_binaries/Cargo.toml +++ b/interop_binaries/Cargo.toml @@ -21,7 +21,7 @@ anyhow.workspace = true backoff = { workspace = true, features = ["tokio"] } base64.workspace = true clap.workspace = true -derivative.workspace = true +educe.workspace = true fixed = { workspace = true, optional = true } futures = { workspace = true } hex = { workspace = true, optional = true } diff --git a/interop_binaries/src/commands/janus_interop_client.rs b/interop_binaries/src/commands/janus_interop_client.rs index 7d5fb6371..5a1d29399 100644 --- a/interop_binaries/src/commands/janus_interop_client.rs +++ b/interop_binaries/src/commands/janus_interop_client.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::Context; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use clap::Parser; -use derivative::Derivative; +use educe::Educe; #[cfg(feature = "fpvec_bounded_l2")] use fixed::{ types::extra::{U15, U31}, @@ -54,13 +54,13 @@ where ) } -#[derive(Derivative, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, Deserialize)] +#[educe(Debug)] struct UploadRequest { task_id: String, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] leader: Url, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] helper: Url, vdaf: VdafObject, measurement: serde_json::Value, diff --git a/interop_binaries/src/commands/janus_interop_collector.rs b/interop_binaries/src/commands/janus_interop_collector.rs index 3afb3fd81..3966c24fb 100644 --- a/interop_binaries/src/commands/janus_interop_collector.rs +++ b/interop_binaries/src/commands/janus_interop_collector.rs @@ -7,7 +7,7 @@ use anyhow::Context; use backoff::ExponentialBackoffBuilder; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use clap::Parser; -use derivative::Derivative; +use educe::Educe; #[cfg(feature = "fpvec_bounded_l2")] use fixed::types::extra::{U15, U31}; #[cfg(feature = "fpvec_bounded_l2")] @@ -42,11 +42,11 @@ use trillium::{Conn, Handler}; use trillium_api::{api, Json, State}; use trillium_router::Router; -#[derive(Derivative, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, Deserialize)] +#[educe(Debug)] struct AddTaskRequest { task_id: String, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] leader: Url, vdaf: VdafObject, collector_authentication_token: String, diff --git a/interop_binaries/src/lib.rs b/interop_binaries/src/lib.rs index 1a680b3ce..6e963d49a 100644 --- a/interop_binaries/src/lib.rs +++ b/interop_binaries/src/lib.rs @@ -1,5 +1,5 @@ use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use janus_aggregator_core::task::{test_util::Task, QueryType}; #[cfg(feature = "fpvec_bounded_l2")] use janus_core::vdaf::Prio3FixedPointBoundedL2VecSumBitSize; @@ -281,13 +281,13 @@ impl From for Role { } } -#[derive(Derivative, Serialize, Deserialize)] -#[derivative(Debug)] +#[derive(Educe, Serialize, Deserialize)] +#[educe(Debug)] pub struct AggregatorAddTaskRequest { pub task_id: TaskId, // uses unpadded base64url - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub leader: Url, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + #[educe(Debug(method(std::fmt::Display::fmt)))] pub helper: Url, pub vdaf: VdafObject, pub leader_authentication_token: String, diff --git a/messages/Cargo.toml b/messages/Cargo.toml index c72becc5f..403cb0e73 100644 --- a/messages/Cargo.toml +++ b/messages/Cargo.toml @@ -15,7 +15,7 @@ test-util = [] [dependencies] anyhow.workspace = true base64.workspace = true -derivative.workspace = true +educe.workspace = true hex = { workspace = true } num_enum = { workspace = true } # Make sure not to enable default-features on prio, as we want clients to be diff --git a/messages/src/lib.rs b/messages/src/lib.rs index f55da2914..f0eea1b93 100644 --- a/messages/src/lib.rs +++ b/messages/src/lib.rs @@ -6,7 +6,7 @@ use self::query_type::{FixedSize, QueryType, TimeInterval}; use anyhow::anyhow; use base64::{display::Base64Display, engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use derivative::Derivative; +use educe::Educe; use num_enum::{FromPrimitive, IntoPrimitive, TryFromPrimitive}; use prio::{ codec::{ @@ -950,16 +950,16 @@ impl Decode for ExtensionType { } /// DAP protocol message representing an HPKE ciphertext. -#[derive(Clone, Derivative, Eq, PartialEq)] -#[derivative(Debug)] +#[derive(Clone, Educe, Eq, PartialEq)] +#[educe(Debug)] pub struct HpkeCiphertext { /// An identifier of the HPKE configuration used to seal the message. config_id: HpkeConfigId, /// An encapsulated HPKE key. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] encapsulated_key: Vec, /// An HPKE ciphertext. - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] payload: Vec, } @@ -1550,11 +1550,11 @@ impl Decode for Query { /// DAP protocol message representing a request from the collector to the leader to provide /// aggregate shares for a given batch. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub struct CollectionReq { query: Query, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: Vec, } @@ -1956,11 +1956,11 @@ impl Decode for AggregateShareAad { } /// DAP protocol message representing one aggregator's share of a single client report. -#[derive(Derivative, Clone, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Educe, Clone, PartialEq, Eq)] +#[educe(Debug)] pub struct ReportShare { metadata: ReportMetadata, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] public_share: Vec, encrypted_input_share: HpkeCiphertext, } @@ -2125,11 +2125,11 @@ impl Decode for PrepareResp { /// DAP protocol message representing result-type-specific data associated with a preparation step /// in a VDAF evaluation. Included in a PrepareResp message. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub enum PrepareStepResult { Continue { - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] message: PingPongMessage, }, Finished, @@ -2324,10 +2324,10 @@ impl Distribution for Standard { /// DAP protocol message representing an aggregation job initialization request from leader to /// helper. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub struct AggregationJobInitializeReq { - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: Vec, partial_batch_selector: PartialBatchSelector, prepare_inits: Vec, @@ -2625,11 +2625,11 @@ impl Decode for BatchSelector { /// DAP protocol message representing a request from the leader to a helper to provide an /// encrypted aggregate of its share of data for a given batch interval. -#[derive(Clone, Derivative, PartialEq, Eq)] -#[derivative(Debug)] +#[derive(Clone, Educe, PartialEq, Eq)] +#[educe(Debug)] pub struct AggregateShareReq { batch_selector: BatchSelector, - #[derivative(Debug = "ignore")] + #[educe(Debug(ignore))] aggregation_parameter: Vec, report_count: u64, checksum: ReportIdChecksum, diff --git a/messages/src/taskprov.rs b/messages/src/taskprov.rs index 01846df6d..9b41bfc2d 100644 --- a/messages/src/taskprov.rs +++ b/messages/src/taskprov.rs @@ -4,7 +4,6 @@ use crate::{Duration, Error, Time, Url}; use anyhow::anyhow; -use derivative::Derivative; use prio::codec::{ decode_u16_items, decode_u8_items, encode_u16_items, encode_u8_items, CodecError, Decode, Encode, @@ -314,8 +313,7 @@ impl Decode for VdafConfig { } } -#[derive(Clone, PartialEq, Eq, Derivative)] -#[derivative(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] #[repr(u32)] #[non_exhaustive] pub enum VdafType { diff --git a/tools/Cargo.toml b/tools/Cargo.toml index b9c22517f..9440031c1 100644 --- a/tools/Cargo.toml +++ b/tools/Cargo.toml @@ -15,7 +15,6 @@ fpvec_bounded_l2 = ["dep:fixed", "janus_collector/fpvec_bounded_l2", "prio/exper anyhow = { workspace = true } base64.workspace = true clap.workspace = true -derivative.workspace = true fixed = { workspace = true, optional = true } janus_collector.workspace = true janus_core.workspace = true