Repository: cloudflare/daphne
Pull request #678 (2024-09-13 09:22:22)

Run clippy over tests as well as normal code


Patch:
diff --git a/.github/workflows/daphneci.yml b/.github/workflows/daphneci.yml
index 4130a7c..81da590 100644
--- a/.github/workflows/daphneci.yml
+++ b/.github/workflows/daphneci.yml
@@ -36,6 +36,8 @@ jobs:
         run: cargo build --all-targets
       - name: Linting
         run: cargo hack clippy --locked --each-feature -- -D warnings
+      - name: Linting Tests
+        run: cargo hack clippy --tests --locked --each-feature -- -D warnings
       - name: Testing
         run: cargo test
       - name: Doc Testing
diff --git a/crates/dapf/src/acceptance/mod.rs b/crates/dapf/src/acceptance/mod.rs
index e9e1a5b..d2852b1 100644
--- a/crates/dapf/src/acceptance/mod.rs
+++ b/crates/dapf/src/acceptance/mod.rs
@@ -645,16 +645,8 @@ impl Test {
 
     pub async fn test_helper(&self, opt: &TestOptions) -> Result<TestDurations> {
         let res = self.test_helper_impl(opt).await;
-        let c = |b: bool| ["F", "T"][b as usize];
-        let metric = self.metrics.test_success.with_label_values(&[
-            c(self.http_client.using_mtls()),
-            c(self.bearer_token.is_some()),
-        ]);
-        if res.is_ok() {
-            metric.inc()
-        } else {
-            metric.set(0)
-        }
+        self.set_sucess_metric_to(res.is_ok());
+
         if let Ok(TestDurations {
             hpke_config_fetch,
             aggregate_init_req,
@@ -744,6 +736,25 @@ impl Test {
             .await?;
         Ok(durations)
     }
+
+    pub fn mock_success(&self) {
+        self.set_sucess_metric_to(true);
+    }
+
+    pub fn mock_failure(&self) {
+        self.set_sucess_metric_to(false);
+    }
+
+    fn set_sucess_metric_to(&self, success: bool) {
+        let c = |b: bool| ["F", "T"][usize::from(b)];
+        self.metrics
+            .test_success
+            .with_label_values(&[
+                c(self.http_client.using_mtls()),
+                c(self.bearer_token.is_some()),
+            ])
+            .set(i64::from(success));
+    }
 }
 
 #[async_trait]
diff --git a/crates/daphne/src/error/aborts.rs b/crates/daphne/src/error/aborts.rs
index b223167..94391a2 100644
--- a/crates/daphne/src/error/aborts.rs
+++ b/crates/daphne/src/error/aborts.rs
@@ -333,26 +333,28 @@ pub struct ProblemDetails {
     pub title: String,
 
     #[serde(rename = "type")]
-    #[serde(skip_serializing_if = "Option::is_none")]
+    #[serde(skip_serializing_if = "Option::is_none", default)]
     pub typ: Option<String>,
 
     #[serde(rename = "taskid")]
     #[serde(
         skip_serializing_if = "Option::is_none",
-        with = "crate::messages::base64url_option"
+        with = "crate::messages::base64url_option",
+        default
     )]
     pub(crate) task_id: Option<TaskId>,
 
     #[serde(rename = "aggregationjobid")]
     #[serde(
         skip_serializing_if = "Option::is_none",
-        with = "crate::messages::base64url_option"
+        with = "crate::messages::base64url_option",
+        default
     )]
     pub(crate) agg_job_id: Option<AggregationJobId>,
 
     pub(crate) instance: String,
 
-    #[serde(skip_serializing_if = "Option::is_none")]
+    #[serde(skip_serializing_if = "Option::is_none", default)]
     pub detail: Option<String>,
 }
 
diff --git a/crates/daphne/src/lib.rs b/crates/daphne/src/lib.rs
index 07ee876..06e20b5 100644
--- a/crates/daphne/src/lib.rs
+++ b/crates/daphne/src/lib.rs
@@ -864,7 +864,6 @@ pub enum DapMeasurement {
         input: Vec<u8>,
         weight: MasticWeight,
     },
-    #[cfg(feature = "experimental")]
     F64Vec(Vec<f64>),
 }
 
@@ -921,7 +920,6 @@ pub enum DapAggregateResult {
     U64Vec(Vec<u64>),
     U128(u128),
     U128Vec(Vec<u128>),
-    #[cfg(feature = "experimental")]
     F64Vec(Vec<f64>),
 }
 
diff --git a/crates/daphne/src/messages/taskprov.rs b/crates/daphne/src/messages/taskprov.rs
index 4216498..4c7e565 100644
--- a/crates/daphne/src/messages/taskprov.rs
+++ b/crates/daphne/src/messages/taskprov.rs
@@ -21,9 +21,7 @@ use super::{decode_u16_prefixed, encode_u16_prefixed};
 // VDAF type codes.
 const VDAF_TYPE_PRIO2: u32 = 0xFFFF_0000;
 pub(crate) const VDAF_TYPE_PRIO3_SUM_VEC_FIELD64_MULTIPROOF_HMAC_SHA256_AES128: u32 = 0xFFFF_1003;
-#[cfg(feature = "experimental")]
 pub(crate) const VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128: u32 = 0xffff_1004;
-#[cfg(feature = "experimental")]
 pub(crate) const VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128: u32 = 0xffff_1005;
 
 // Differential privacy mechanism types.
@@ -41,11 +39,9 @@ pub enum VdafTypeVar {
         chunk_length: u32,
         num_proofs: u8,
     },
-    #[cfg(feature = "experimental")]
     Pine32HmacSha256Aes128 {
         param: PineParam,
     },
-    #[cfg(feature = "experimental")]
     Pine64HmacSha256Aes128 {
         param: PineParam,
     },
@@ -150,12 +146,10 @@ impl ParameterizedEncode<DapVersion> for VdafTypeVar {
                 chunk_length.encode(bytes)?;
                 num_proofs.encode(bytes)?;
             }
-            #[cfg(feature = "experimental")]
             Self::Pine32HmacSha256Aes128 { param } => {
                 VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128.encode(bytes)?;
                 param.encode(bytes)?;
             }
-            #[cfg(feature = "experimental")]
             Self::Pine64HmacSha256Aes128 { param } => {
                 VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128.encode(bytes)?;
                 param.encode(bytes)?;
@@ -187,11 +181,9 @@ impl ParameterizedDecode<(DapVersion, Option<usize>)> for VdafTypeVar {
                     num_proofs: u8::decode(bytes)?,
                 })
             }
-            #[cfg(feature = "experimental")]
             (.., VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128) => Ok(Self::Pine32HmacSha256Aes128 {
                 param: PineParam::decode(bytes)?,
             }),
-            #[cfg(feature = "experimental")]
             (.., VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128) => Ok(Self::Pine64HmacSha256Aes128 {
                 param: PineParam::decode(bytes)?,
             }),
@@ -645,7 +637,6 @@ mod tests {
 
     test_versions! { roundtrip_vdaf_config_prio3_sum_vec_field64_multiproof_hmac_sha256_aes128 }
 
-    #[cfg(feature = "experimental")]
     fn roundtrip_vdaf_config_pine32_hmac_sha256_aes128(version: DapVersion) {
         let vdaf_config = VdafConfig {
             dp_config: DpConfig::None,
@@ -671,10 +662,8 @@ mod tests {
         );
     }
 
-    #[cfg(feature = "experimental")]
     test_versions! { roundtrip_vdaf_config_pine32_hmac_sha256_aes128 }
 
-    #[cfg(feature = "experimental")]
     fn roundtrip_vdaf_config_pine64_hmac_sha256_aes128(version: DapVersion) {
         let vdaf_config = VdafConfig {
             dp_config: DpConfig::None,
@@ -700,7 +689,6 @@ mod tests {
         );
     }
 
-    #[cfg(feature = "experimental")]
     test_versions! { roundtrip_vdaf_config_pine64_hmac_sha256_aes128 }
 
     fn roundtrip_vdaf_config_not_implemented(version: DapVersion) {
diff --git a/crates/daphne/src/pine/mod.rs b/crates/daphne/src/pine/mod.rs
index 42f72d6..7f7a2d1 100644
--- a/crates/daphne/src/pine/mod.rs
+++ b/crates/daphne/src/pine/mod.rs
@@ -46,7 +46,7 @@ pub struct Pine<F, X, const SEED_SIZE: usize> {
     // PINE parameters
     num_proofs: u8,
     num_proofs_sq_norm_equal: u8,
-    encoded_gradient_len: usize,
+    encoded_gradient_and_sq_norm_len: usize,
     encoded_input_len: usize,
 
     algorithm_id: u32,
@@ -171,20 +171,13 @@ impl<F: FftFriendlyFieldElement, X, const SEED_SIZE: usize> Pine<F, X, SEED_SIZE
             ));
         }
 
-        // 24 is the largest number of fractional bits that we know we can support.
-        if param.frac_bits > 24 {
-            return Err(VdafError::Uncategorized(
-                "init failed: too many fractional bits".into(),
-            ));
-        }
-
         if param.dimension == 0 {
             return Err(VdafError::Uncategorized(
                 "init failed: 0-dimension inputs are invalid".into(),
             ));
         }
 
-        if param.frac_bits > 128 {
+        if param.frac_bits >= 128 {
             return Err(VdafError::Uncategorized(
                 "init failed: number of fractional bits must not exceed 128".into(),
             ));
@@ -208,6 +201,11 @@ impl<F: FftFriendlyFieldElement, X, const SEED_SIZE: usize> Pine<F, X, SEED_SIZE
                     "init failed: failed to convert squared norm bound to field integer: {e}"
                 ))
             })?;
+            if sq_norm_bound >= F::modulus() {
+                return Err(VdafError::Uncategorized(
+                    "init failed: squared norm bound is too large for field".into(),
+                ));
+            }
             let sq_norm_bound = F::from(sq_norm_bound);
             (sq_norm_bound, sq_norm_bits)
         };
@@ -228,26 +226,36 @@ impl<F: FftFriendlyFieldElement, X, const SEED_SIZE: usize> Pine<F, X, SEED_SIZE
                     "init failed: failed to convert wraparound test bound to field integer: {e}"
                 ))
             })?;
+            if wr_test_bound >= F::modulus() {
+                return Err(VdafError::Uncategorized(
+                    "init failed: wraparound test bound is too large for field".into(),
+                ));
+            }
             let wr_test_bound = F::from(wr_test_bound);
             (wr_test_bound, wr_test_bits)
         };
 
-        // FLP parameters
+        // FlP encoded measurement length parameters. The components of the input are:
         //
-        // Length of the FLP input prefix that is used to derive the wraparound
-        // joint randomness.
-        let encoded_gradient_len = param.dimension + 2 * sq_norm_bits;
-
-        // Length of the FLP input prefx that includes everything but the wraparound
-        // check results.
-        let encoded_input_len = encoded_gradient_len + (1 + wr_test_bits) * param.num_wr_tests;
+        // * gradient (length `dimension`)
+        // * reported squared norm (`2 * sq_norm_bits`)
+        // * reported wraparound test results (`1 + wr_test_bits * num_wr_tests`)
+        // * wraparound test results (`num_wr_tests`)
+        //
+        // Length of the gradient and reported squared norm.
+        let encoded_gradient_and_sq_norm_len = param.dimension + 2 * sq_norm_bits;
 
-        // The length of the fully encodeed measurement passed to each validity circuit.
-        let input_len = encoded_input_len + param.num_wr_tests;
+        // Length of the gradient, reported squared norm, and reported test results.
+        let encoded_input_len =
+            encoded_gradient_and_sq_norm_len + (1 + wr_test_bits) * param.num_wr_tests;
 
-        // Length of the bit-checked portion of the encoded measurement.
+        // Length of the bit-checked portion of the encoded measurement: the reported squared norm
+        // and the reported wraparound test results.
         let bit_checked_len = 2 * sq_norm_bits + (1 + wr_test_bits) * param.num_wr_tests;
 
+        // The length of the fully encoded measurement passed to each validity circuit.
+        let input_len = encoded_input_len + param.num_wr_tests;
+
         // Number of gadget calls. The gadget is used for the bit checks, wraparound tests, and
         // squared norm computation.
         let gadget_calls = chunk_count(param.chunk_len, bit_checked_len)
@@ -281,7 +289,7 @@ impl<F: FftFriendlyFieldElement, X, const SEED_SIZE: usize> Pine<F, X, SEED_SIZE
             },
             num_proofs: param.num_proofs,
             num_proofs_sq_norm_equal: param.num_proofs_sq_norm_equal,
-            encoded_gradient_len,
+            encoded_gradient_and_sq_norm_len,
             encoded_input_len,
             algorithm_id,
             phantom_data: PhantomData,
diff --git a/crates/daphne/src/pine/vdaf.rs b/crates/daphne/src/pine/vdaf.rs
index 4038264..96e8d50 100644
--- a/crates/daphne/src/pine/vdaf.rs
+++ b/crates/daphne/src/pine/vdaf.rs
@@ -201,8 +201,8 @@ impl<F: FftFriendlyFieldElement, X: Xof<SEED_SIZE>, const SEED_SIZE: usize> Pine
         for (m, s1) in meas.iter().zip(meas_share_1.iter().take(meas.len())) {
             meas_share_0.push(*m - *s1);
         }
-        debug_assert_eq!(meas.len(), self.encoded_gradient_len);
-        debug_assert_eq!(meas_share_0.len(), self.encoded_gradient_len);
+        debug_assert_eq!(meas.len(), self.encoded_gradient_and_sq_norm_len);
+        debug_assert_eq!(meas_share_0.len(), self.encoded_gradient_and_sq_norm_len);
         debug_assert_eq!(meas_share_1.len(), self.encoded_input_len);
 
         let wr_joint_rand_parts = [
@@ -217,7 +217,7 @@ impl<F: FftFriendlyFieldElement, X: Xof<SEED_SIZE>, const SEED_SIZE: usize> Pine
                 1,
                 &wr_blind_1,
                 nonce,
-                &meas_share_1[..self.encoded_gradient_len],
+                &meas_share_1[..self.encoded_gradient_and_sq_norm_len],
                 USAGE_WR_JOINT_RAND_PART,
             ),
         ];
@@ -425,7 +425,7 @@ impl<F: FftFriendlyFieldElement, X: Xof<SEED_SIZE>, const SEED_SIZE: usize>
             agg_id.try_into().unwrap(),
             wr_blind.as_ref(),
             nonce,
-            &meas_share[..self.encoded_gradient_len],
+            &meas_share[..self.encoded_gradient_and_sq_norm_len],
             USAGE_WR_JOINT_RAND_PART,
         );
 
diff --git a/crates/daphne/src/protocol/aggregator.rs b/crates/daphne/src/protocol/aggregator.rs
index a1e4087..39a82a1 100644
--- a/crates/daphne/src/protocol/aggregator.rs
+++ b/crates/daphne/src/protocol/aggregator.rs
@@ -332,7 +332,6 @@ impl EarlyReportStateInitialized {
                 &public_share,
                 input_share.as_ref(),
             ),
-            #[cfg(feature = "experimental")]
             VdafConfig::Pine(pine) => pine.prep_init(
                 vdaf_verify_key,
                 agg_id,
@@ -692,7 +691,6 @@ impl DapTaskConfig {
                                 helper_prep_share.clone(),
                                 leader_prep_share,
                             ),
-                            #[cfg(feature = "experimental")]
                             VdafConfig::Pine(pine) => pine.prep_finish_from_shares(
                                 1,
                                 helper_prep_state.clone(),
@@ -823,7 +821,6 @@ impl DapTaskConfig {
                 }
                 #[cfg(feature = "experimental")]
                 VdafConfig::Mastic { .. } => mastic_prep_finish(leader.prep_state, prep_msg),
-                #[cfg(feature = "experimental")]
                 VdafConfig::Pine(pine) => pine.prep_finish(leader.prep_state, prep_msg),
             };
 
diff --git a/crates/daphne/src/protocol/client.rs b/crates/daphne/src/protocol/client.rs
index 8d3c505..ca62dc6 100644
--- a/crates/daphne/src/protocol/client.rs
+++ b/crates/daphne/src/protocol/client.rs
@@ -143,7 +143,6 @@ impl VdafConfig {
                 input_size,
                 weight_config,
             } => Ok(mastic_shard(*input_size, *weight_config, measurement)?),
-            #[cfg(feature = "experimental")]
             VdafConfig::Pine(pine) => Ok(pine.shard(measurement, nonce)?),
         }
     }
diff --git a/crates/daphne/src/protocol/collector.rs b/crates/daphne/src/protocol/collector.rs
index d96fbea..cb32dcf 100644
--- a/crates/daphne/src/protocol/collector.rs
+++ b/crates/daphne/src/protocol/collector.rs
@@ -89,7 +89,6 @@ impl VdafConfig {
                 input_size: _,
                 weight_config,
             } => mastic_unshard(*weight_config, agg_param, agg_shares),
-            #[cfg(feature = "experimental")]
             Self::Pine(pine) => pine.unshard(num_measurements, agg_shares),
         }
         .map_err(|e| fatal_error!(err = ?e, "failed to unshard agg_shares"))
diff --git a/crates/daphne/src/roles/leader/in_memory_leader.rs b/crates/daphne/src/roles/leader/in_memory_leader.rs
index a024dc7..5ea9a2a 100644
--- a/crates/daphne/src/roles/leader/in_memory_leader.rs
+++ b/crates/daphne/src/roles/leader/in_memory_leader.rs
@@ -22,7 +22,7 @@ use crate::{
 };
 
 #[derive(Default)]
-#[cfg_attr(feature = "test-utils", derive(deepsize::DeepSizeOf))]
+#[cfg_attr(any(test, feature = "test-utils"), derive(deepsize::DeepSizeOf))]
 pub struct InMemoryLeaderState {
     work_queue: VecDeque<WorkItem>,
     per_task: HashMap<TaskId, MockLeaderMemoryPerTask>,
@@ -233,7 +233,7 @@ impl InMemoryLeaderState {
 }
 
 #[derive(Default)]
-#[cfg_attr(feature = "test-utils", derive(deepsize::DeepSizeOf))]
+#[cfg_attr(any(test, feature = "test-utils"), derive(deepsize::DeepSizeOf))]
 struct MockLeaderMemoryPerTask {
     pending_reports: HashMap<DapBatchBucket, VecDeque<Report>>,
     coll_jobs: HashMap<CollectionJobId, DapCollectionJob>,
diff --git a/crates/daphne/src/roles/mod.rs b/crates/daphne/src/roles/mod.rs
index 6f05807..a8db54e 100644
--- a/crates/daphne/src/roles/mod.rs
+++ b/crates/daphne/src/roles/mod.rs
@@ -1719,9 +1719,8 @@ mod test {
 
     async_test_versions! { e2e_taskprov_prio3_sum_vec_field64_multiproof_hmac_sha256_aes128 }
 
-    #[cfg(feature = "experimental")]
     async fn e2e_taskprov_pine32_hmac_sha256_aes128(version: DapVersion) {
-        use crate::{pine::PineParam, vdaf::PineConfig};
+        use crate::{pine::PineParam, vdaf::pine::PineConfig};
         e2e_taskprov(
             version,
             VdafConfig::Pine(PineConfig::Field32HmacSha256Aes128 {
@@ -1742,12 +1741,10 @@ mod test {
         .await;
     }
 
-    #[cfg(feature = "experimental")]
     async_test_versions! { e2e_taskprov_pine32_hmac_sha256_aes128 }
 
-    #[cfg(feature = "experimental")]
     async fn e2e_taskprov_pine64_hmac_sha256_aes128(version: DapVersion) {
-        use crate::{pine::PineParam, vdaf::PineConfig};
+        use crate::{pine::PineParam, vdaf::pine::PineConfig};
         e2e_taskprov(
             version,
             VdafConfig::Pine(PineConfig::Field64HmacSha256Aes128 {
@@ -1768,7 +1765,6 @@ mod test {
         .await;
     }
 
-    #[cfg(feature = "experimental")]
     async_test_versions! { e2e_taskprov_pine64_hmac_sha256_aes128 }
 
     // Test multiple tasks in flight at once.
diff --git a/crates/daphne/src/taskprov.rs b/crates/daphne/src/taskprov.rs
index b2c03b1..d1eac2a 100644
--- a/crates/daphne/src/taskprov.rs
+++ b/crates/daphne/src/taskprov.rs
@@ -19,7 +19,6 @@ use crate::{
     DapAbort, DapError, DapQueryConfig, DapRequest, DapTaskConfig, DapTaskConfigMethod, DapVersion,
     Prio3Config, VdafConfig,
 };
-#[cfg(feature = "experimental")]
 use crate::{
     pine::PineParam,
     vdaf::pine::{pine32_hmac_sha256_aes128, pine64_hmac_sha256_aes128, PineConfig},
@@ -187,7 +186,6 @@ impl DapQueryConfig {
     }
 }
 
-#[cfg(feature = "experimental")]
 impl PineParam {
     fn opt_out_reason(&self, min_proofs: u8) -> Option<String> {
         const MAX_DIM: usize = 300_000;
@@ -269,7 +267,6 @@ impl VdafConfig {
                     },
                 ))
             }
-            #[cfg(feature = "experimental")]
             (_, VdafTypeVar::Pine32HmacSha256Aes128 { param }) => {
                 if let Err(e) = pine32_hmac_sha256_aes128(&param) {
                     Err(DapAbort::InvalidTask {
@@ -287,7 +284,6 @@ impl VdafConfig {
                     }))
                 }
             }
-            #[cfg(feature = "experimental")]
             (_, VdafTypeVar::Pine64HmacSha256Aes128 { param }) => {
                 if let Err(e) = pine64_hmac_sha256_aes128(&param) {
                     Err(DapAbort::InvalidTask {
@@ -453,11 +449,9 @@ impl TryFrom<&VdafConfig> for messages::taskprov::VdafTypeVar {
             VdafConfig::Mastic { .. } => Err(fatal_error!(
                 err = format!("{vdaf_config} is not currently supported for taskprov")
             )),
-            #[cfg(feature = "experimental")]
             VdafConfig::Pine(PineConfig::Field32HmacSha256Aes128 { param }) => {
                 Ok(Self::Pine32HmacSha256Aes128 { param: *param })
             }
-            #[cfg(feature = "experimental")]
             VdafConfig::Pine(PineConfig::Field64HmacSha256Aes128 { param }) => {
                 Ok(Self::Pine64HmacSha256Aes128 { param: *param })
             }
diff --git a/crates/daphne/src/vdaf/mod.rs b/crates/daphne/src/vdaf/mod.rs
index 44a4bfc..bf35f1b 100644
--- a/crates/daphne/src/vdaf/mod.rs
+++ b/crates/daphne/src/vdaf/mod.rs
@@ -6,14 +6,13 @@
 
 #[cfg(feature = "experimental")]
 pub(crate) mod mastic;
-#[cfg(feature = "experimental")]
 pub(crate) mod pine;
 pub(crate) mod prio2;
 pub(crate) mod prio3;
 
-#[cfg(feature = "experimental")]
 use crate::pine::vdaf::PinePrepState;
 use crate::{fatal_error, DapError};
+use pine::PineConfig;
 #[cfg(any(test, feature = "test-utils", feature = "experimental"))]
 use prio::field::FieldElement;
 use prio::{
@@ -32,7 +31,7 @@ use serde::{Deserialize, Serialize};
 use std::io::Read;
 
 #[cfg(feature = "experimental")]
-pub use self::{mastic::MasticWeightConfig, pine::PineConfig};
+pub use self::mastic::MasticWeightConfig;
 
 #[derive(Debug, thiserror::Error)]
 pub(crate) enum VdafError {
@@ -61,7 +60,6 @@ pub enum VdafConfig {
         /// The type of each weight.
         weight_config: MasticWeightConfig,
     },
-    #[cfg(feature = "experimental")]
     Pine(PineConfig),
 }
 
@@ -83,7 +81,6 @@ impl std::fmt::Display for VdafConfig {
                 input_size,
                 weight_config,
             } => write!(f, "Mastic({input_size}, {weight_config})"),
-            #[cfg(feature = "experimental")]
             VdafConfig::Pine(pine_config) => write!(f, "{pine_config}"),
         }
     }
@@ -202,9 +199,7 @@ pub enum VdafPrepState {
     Mastic {
         out_share: Vec<Field64>,
     },
-    #[cfg(feature = "experimental")]
     Pine64HmacSha256Aes128(PinePrepState<Field64, 32>),
-    #[cfg(feature = "experimental")]
     Pine32HmacSha256Aes128(PinePrepState<FieldPrio2, 32>),
 }
 
@@ -219,11 +214,11 @@ impl deepsize::DeepSizeOf for VdafPrepState {
             Self::Prio2(_)
             | Self::Prio3Field64(_)
             | Self::Prio3Field64HmacSha256Aes128(_)
-            | Self::Prio3Field128(_) => 0,
-            #[cfg(feature = "experimental")]
-            Self::Mastic { .. }
+            | Self::Prio3Field128(_)
             | Self::Pine64HmacSha256Aes128(_)
             | Self::Pine32HmacSha256Aes128(_) => 0,
+            #[cfg(feature = "experimental")]
+            Self::Mastic { .. } => 0,
         }
     }
 }
@@ -238,9 +233,7 @@ pub enum VdafPrepShare {
     Prio3Field128(Prio3PrepareShare<Field128, 16>),
     #[cfg(feature = "experimental")]
     Mastic(Field64),
-    #[cfg(feature = "experimental")]
     Pine64HmacSha256Aes128(crate::pine::msg::PrepShare<Field64, 32>),
-    #[cfg(feature = "experimental")]
     Pine32HmacSha256Aes128(crate::pine::msg::PrepShare<FieldPrio2, 32>),
 }
 
@@ -257,11 +250,11 @@ impl deepsize::DeepSizeOf for VdafPrepShare {
             // type.
             Self::Prio3Field64(..)
             | Self::Prio3Field64HmacSha256Aes128(..)
-            | Self::Prio3Field128(..) => 0,
-            #[cfg(feature = "experimental")]
-            Self::Mastic(..)
+            | Self::Prio3Field128(..)
             | Self::Pine64HmacSha256Aes128(_)
             | Self::Pine32HmacSha256Aes128(_) => 0,
+            #[cfg(feature = "experimental")]
+            Self::Mastic(..) => 0,
         }
     }
 }
@@ -275,9 +268,7 @@ impl Encode for VdafPrepShare {
             Self::Prio2(share) => share.encode(bytes),
             #[cfg(feature = "experimental")]
             Self::Mastic(share) => share.encode(bytes),
-            #[cfg(feature = "experimental")]
             Self::Pine64HmacSha256Aes128(share) => share.encode(bytes),
-            #[cfg(feature = "experimental")]
             Self::Pine32HmacSha256Aes128(share) => share.encode(bytes),
         }
     }
@@ -307,13 +298,11 @@ impl ParameterizedDecode<VdafPrepState> for VdafPrepShare {
             VdafPrepState::Mastic { .. } => {
                 todo!("mastic: decoding of prep messages is not implemented")
             }
-            #[cfg(feature = "experimental")]
             VdafPrepState::Pine64HmacSha256Aes128(state) => {
                 Ok(VdafPrepShare::Pine64HmacSha256Aes128(
                     crate::pine::msg::PrepShare::decode_with_param(state, bytes)?,
                 ))
             }
-            #[cfg(feature = "experimental")]
             VdafPrepState::Pine32HmacSha256Aes128(state) => {
                 Ok(VdafPrepShare::Pine32HmacSha256Aes128(
                     crate::pine::msg::PrepShare::decode_with_param(state, bytes)?,
@@ -360,7 +349,6 @@ impl VdafConfig {
             Self::Prio3(..) => VdafVerifyKey::L16([0; 16]),
             #[cfg(feature = "experimental")]
             Self::Mastic { .. } => VdafVerifyKey::L16([0; 16]),
-            #[cfg(feature = "experimental")]
             Self::Pine(..) => VdafVerifyKey::L32([0; 32]),
         }
     }
@@ -379,7 +367,6 @@ impl VdafConfig {
             Self::Mastic { .. } => Ok(VdafVerifyKey::L16(
                 <[u8; 16]>::try_from(bytes).map_err(|e| CodecError::Other(Box::new(e)))?,
             )),
-            #[cfg(feature = "experimental")]
             Self::Pine(..) => Ok(VdafVerifyKey::L32(
                 <[u8; 32]>::try_from(bytes).map_err(|e| CodecError::Other(Box::new(e)))?,
             )),
@@ -401,7 +388,6 @@ impl VdafConfig {
             Self::Prio3(..) | Self::Prio2 { .. } => agg_param.is_empty(),
             #[cfg(feature = "experimental")]
             Self::Mastic { .. } => true,
-            #[cfg(feature = "experimental")]
             Self::Pine(..) => agg_param.is_empty(),
         }
     }


Test patch:
diff --git a/crates/daphne/src/pine/test_vec/mod.rs b/crates/daphne/src/pine/test_vec/mod.rs
index aff8c0d..b869c22 100644
--- a/crates/daphne/src/pine/test_vec/mod.rs
+++ b/crates/daphne/src/pine/test_vec/mod.rs
@@ -2,7 +2,6 @@
 
 //! Tools for evaluating PINE test vectors.
 
-#[cfg(feature = "experimental")]
 use crate::messages::taskprov::{
     VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128, VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128,
 };
@@ -15,7 +14,6 @@ use prio::{
         Aggregator, Collector, PrepareTransition,
     },
 };
-#[cfg(feature = "experimental")]
 use prio::{field::FieldPrio2, vdaf::xof::XofHmacSha256Aes128};
 use serde::Deserialize;
 
@@ -252,112 +250,96 @@ fn pine128_3() {
         .run::<Field128, XofTurboShake128, 16>(PINE_TEST);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_0() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_0.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_1() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_1.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_2() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_2.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_3() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_3.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_4() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_4.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_5() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_5.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_6() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_6.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine32_hmac_sha256_aes128_7() {
     TestVec::from_str(include_str!("01/Pine32HmacSha256Aes128_7.json"))
         .run::<FieldPrio2, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD32_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_0() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_0.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_1() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_1.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_2() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_2.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_3() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_3.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_4() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_4.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_5() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_5.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_6() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_6.json"))
         .run::<Field64, XofHmacSha256Aes128, 32>(VDAF_TYPE_PINE_FIELD64_HMAC_SHA256_AES128);
 }
 
-#[cfg(feature = "experimental")]
 #[test]
 fn pine64_hmac_sha256_aes128_7() {
     TestVec::from_str(include_str!("01/Pine64HmacSha256Aes128_7.json"))