Repository: cloudflare/daphne
Pull request #370 (2023-07-13 23:02:19)

Upgrade Libprio to 0.13.0 / move to VDAF-06
I upgraded Libprio and implemented the new histogram format introduced by VDAF-06.

 I have one question: histogram measurements are of type `usize` in Libprio (https://github.com/divviup/libprio-rs/blob/main/src/flp/types.rs#L353), but so far we've been using the `DapMeasurement::U64` type for histograms. Right now I am casting to an `usize`, which could cause problems on 32-bit systems. Should we add a U32 measurement type, or is it fine to keep things as they are?

Two other notes, about interoperability:
- the TaskProv spec doesn't support VDAF-06, so I had to comment out some test vectors until the spec catches up. See https://github.com/wangshan/draft-wang-ppm-dap-taskprov/issues/33
- similarly for https://datatracker.ietf.org/doc/html/draft-dcook-ppm-dap-interop-test-design-04#name-internal-test-add_task. I still added an endpoint as it might be useful for debugging, as a temporary fix for https://github.com/cloudflare/daphne/issues/271


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 229a445..3ce7604 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -50,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "aes"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
+checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
 dependencies = [
  "cfg-if",
  "cipher 0.4.4",
@@ -61,14 +61,14 @@ dependencies = [
 
 [[package]]
 name = "aes-gcm"
-version = "0.9.4"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
+checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f"
 dependencies = [
  "aead 0.4.3",
  "aes 0.7.5",
  "cipher 0.3.0",
- "ctr 0.8.0",
+ "ctr 0.7.0",
  "ghash 0.4.4",
  "subtle",
 ]
@@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237"
 dependencies = [
  "aead 0.5.2",
- "aes 0.8.2",
+ "aes 0.8.3",
  "cipher 0.4.4",
  "ctr 0.9.2",
  "ghash 0.5.0",
@@ -609,9 +609,9 @@ dependencies = [
 
 [[package]]
 name = "crypto-mac"
-version = "0.11.1"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
+checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e"
 dependencies = [
  "generic-array",
  "subtle",
@@ -619,9 +619,9 @@ dependencies = [
 
 [[package]]
 name = "ctr"
-version = "0.8.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
+checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481"
 dependencies = [
  "cipher 0.3.0",
 ]
@@ -1155,7 +1155,7 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8603fbb7674b627cb9f3de6ae5ba8b7e621ef5fdea6489363cb4bef26e5fce52"
 dependencies = [
- "aes-gcm 0.9.4",
+ "aes-gcm 0.9.2",
  "chacha20poly1305",
  "getrandom",
  "hkdf",
@@ -1777,7 +1777,7 @@ checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
 dependencies = [
  "cpufeatures",
  "opaque-debug",
- "universal-hash 0.4.1",
+ "universal-hash 0.4.0",
 ]
 
 [[package]]
@@ -1789,7 +1789,7 @@ dependencies = [
  "cfg-if",
  "cpufeatures",
  "opaque-debug",
- "universal-hash 0.4.1",
+ "universal-hash 0.4.0",
 ]
 
 [[package]]
@@ -1812,11 +1812,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "prio"
-version = "0.12.2"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9028a8aba9ba6b647c6d6931c20473d1119079a68d9898c07a488c5180dccb58"
+checksum = "16d673a50806c380e70ff48884611bbe4d100a029f522f2ea9cf106cf3d9c922"
 dependencies = [
- "aes 0.8.2",
+ "aes 0.8.3",
  "aes-gcm 0.10.2",
  "base64 0.21.2",
  "byteorder",
@@ -2338,9 +2338,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "subtle"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
 
 [[package]]
 name = "subtle-ng"
@@ -2640,9 +2640,9 @@ dependencies = [
 
 [[package]]
 name = "universal-hash"
-version = "0.4.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
+checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
 dependencies = [
  "generic-array",
  "subtle",
diff --git a/Cargo.toml b/Cargo.toml
index c66b94a..0398b9b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ hpke-rs-crypto = "=0.1.1"
 hpke-rs-rust-crypto = "=0.1.1"
 matchit = "0.7.0"
 paste = "1.0.13"
-prio = "0.12.2"
+prio = "0.13.0"
 prometheus = "0.13.3"
 rand = "0.8.5"
 reqwest = "0.11.18"
diff --git a/daphne/src/lib.rs b/daphne/src/lib.rs
index 1204ff7..ab9e220 100644
--- a/daphne/src/lib.rs
+++ b/daphne/src/lib.rs
@@ -662,9 +662,9 @@ pub enum Prio3Config {
     /// equal to `0` or `1`.
     Count,
 
-    /// A histogram for estimating the distribution of 64-bit, unsigned integers using pre-defined
-    /// bucket boundaries.
-    Histogram { buckets: Vec<u64> },
+    /// A histogram for estimating the distribution of 64-bit, unsigned integers where each
+    /// measurement is a bucket index in range `[0, len)`.
+    Histogram { len: usize },
 
     /// The sum of 64-bit, unsigned integers. Each measurement is an integer in range `[0,
     /// 2^bits)`.
@@ -679,9 +679,7 @@ impl Display for Prio3Config {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
             Prio3Config::Count => write!(f, "Count"),
-            Prio3Config::Histogram { buckets } => {
-                write!(f, "Histogram({})", buckets.len())
-            }
+            Prio3Config::Histogram { len } => write!(f, "Histogram({len})"),
             Prio3Config::Sum { bits } => write!(f, "Sum({bits})"),
             Prio3Config::SumVec { bits, len } => write!(f, "SumVec({bits},{len})"),
         }
diff --git a/daphne/src/messages/taskprov.rs b/daphne/src/messages/taskprov.rs
index c82871a..cc18847 100644
--- a/daphne/src/messages/taskprov.rs
+++ b/daphne/src/messages/taskprov.rs
@@ -10,8 +10,8 @@ use crate::messages::{
 };
 use crate::taskprov::TaskprovVersion;
 use prio::codec::{
-    decode_u16_items, decode_u24_items, decode_u8_items, encode_u16_items, encode_u24_items,
-    encode_u8_items, CodecError, Decode, Encode, ParameterizedDecode, ParameterizedEncode,
+    decode_u16_items, decode_u8_items, encode_u16_items, encode_u8_items, CodecError, Decode,
+    Encode, ParameterizedDecode, ParameterizedEncode,
 };
 use ring::hkdf::KeyType;
 use serde::{Deserialize, Serialize};
@@ -54,7 +54,9 @@ impl KeyType for VdafType {
 pub enum VdafTypeVar {
     Prio3Aes128Count,
     Prio3Aes128Sum { bit_length: u8 },
-    Prio3Aes128Histogram { buckets: Vec<u64> },
+    // NOTE: this doesn't comply with the TaskProv spec, which doesn't match the VDAF-06 spec.
+    // Tracking the issue here: https://github.com/wangshan/draft-wang-ppm-dap-taskprov/issues/33.
+    Prio3Aes128Histogram { len: u32 },
     Poplar1Aes128 { bit_length: u16 },
     NotImplemented(u32),
 }
@@ -67,9 +69,9 @@ impl Encode for VdafTypeVar {
                 VDAF_TYPE_PRIO3_AES128_SUM.encode(bytes);
                 bit_length.encode(bytes);
             }
-            VdafTypeVar::Prio3Aes128Histogram { buckets } => {
+            VdafTypeVar::Prio3Aes128Histogram { len } => {
                 VDAF_TYPE_PRIO3_AES128_HISTOGRAM.encode(bytes);
-                encode_u24_items(bytes, &(), buckets);
+                len.encode(bytes);
             }
             VdafTypeVar::Poplar1Aes128 { bit_length } => {
                 VDAF_TYPE_POPLAR1_AES128.encode(bytes);
@@ -91,7 +93,7 @@ impl Decode for VdafTypeVar {
                 bit_length: u8::decode(bytes)?,
             }),
             VDAF_TYPE_PRIO3_AES128_HISTOGRAM => Ok(Self::Prio3Aes128Histogram {
-                buckets: decode_u24_items(&(), bytes)?,
+                len: u32::decode(bytes)?,
             }),
             VDAF_TYPE_POPLAR1_AES128 => Ok(Self::Poplar1Aes128 {
                 bit_length: u16::decode(bytes)?,
diff --git a/daphne/src/taskprov.rs b/daphne/src/taskprov.rs
index 9fd325f..cf735ff 100644
--- a/daphne/src/taskprov.rs
+++ b/daphne/src/taskprov.rs
@@ -242,8 +242,10 @@ impl From<VdafTypeVar> for VdafConfig {
     fn from(var: VdafTypeVar) -> Self {
         match var {
             VdafTypeVar::Prio3Aes128Count => VdafConfig::Prio3(Prio3Config::Count),
-            VdafTypeVar::Prio3Aes128Histogram { buckets } => {
-                VdafConfig::Prio3(Prio3Config::Histogram { buckets })
+            VdafTypeVar::Prio3Aes128Histogram { len } => {
+                VdafConfig::Prio3(Prio3Config::Histogram {
+                    len: len.try_into().unwrap(),
+                })
             }
             VdafTypeVar::Prio3Aes128Sum { bit_length } => VdafConfig::Prio3(Prio3Config::Sum {
                 bits: bit_length.into(),
diff --git a/daphne/src/vdaf/prio3.rs b/daphne/src/vdaf/prio3.rs
index 0702d56..fd7708a 100644
--- a/daphne/src/vdaf/prio3.rs
+++ b/daphne/src/vdaf/prio3.rs
@@ -52,9 +52,10 @@ pub(crate) fn prio3_shard(
             let vdaf = Prio3::new_count(2)?;
             Ok(shard!(vdaf, &measurement, nonce))
         }
-        (Prio3Config::Histogram { buckets }, DapMeasurement::U64(measurement)) => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
-            Ok(shard!(vdaf, &(measurement as u128), nonce))
+        (Prio3Config::Histogram { len }, DapMeasurement::U64(measurement)) => {
+            let vdaf = Prio3::new_histogram(2, *len)?;
+            let m: usize = measurement.try_into().unwrap();
+            Ok(shard!(vdaf, &m, nonce))
         }
         (Prio3Config::Sum { bits }, DapMeasurement::U64(measurement)) => {
             let vdaf = Prio3::new_sum(2, *bits)?;
@@ -121,8 +122,8 @@ pub(crate) fn prio3_prepare_init(
                 VdafPrepMessage::Prio3ShareField64(share),
             ))
         }
-        Prio3Config::Histogram { buckets } => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
+        Prio3Config::Histogram { len } => {
+            let vdaf = Prio3::new_histogram(2, *len)?;
             let (state, share) = prep_init!(
                 vdaf,
                 verify_key,
@@ -213,11 +214,11 @@ pub(crate) fn prio3_leader_prepare_finish(
             (agg_share, outbound)
         }
         (
-            Prio3Config::Histogram { buckets },
+            Prio3Config::Histogram { len },
             VdafPrepState::Prio3Field128(state),
             VdafPrepMessage::Prio3ShareField128(share),
         ) => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
+            let vdaf = Prio3::new_histogram(2, *len)?;
             let (out_share, outbound) = leader_prep_fin!(vdaf, state, share, helper_share_data);
             let agg_share = VdafAggregateShare::Field128(vdaf.aggregate(&(), [out_share])?);
             (agg_share, outbound)
@@ -281,8 +282,8 @@ pub(crate) fn prio3_helper_prepare_finish(
             let out_share = helper_prep_fin!(vdaf, state, peer_message_data);
             VdafAggregateShare::Field64(vdaf.aggregate(&(), [out_share])?)
         }
-        (Prio3Config::Histogram { buckets }, VdafPrepState::Prio3Field128(state)) => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
+        (Prio3Config::Histogram { len }, VdafPrepState::Prio3Field128(state)) => {
+            let vdaf = Prio3::new_histogram(2, *len)?;
             let out_share = helper_prep_fin!(vdaf, state, peer_message_data);
             VdafAggregateShare::Field128(vdaf.aggregate(&(), [out_share])?)
         }
@@ -315,8 +316,8 @@ pub(crate) fn prio3_decode_prepare_state(
                 Prio3PrepareState::decode_with_param(&(&vdaf, agg_id), bytes)?,
             ))
         }
-        Prio3Config::Histogram { buckets } => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
+        Prio3Config::Histogram { len } => {
+            let vdaf = Prio3::new_histogram(2, *len)?;
             Ok(VdafPrepState::Prio3Field128(
                 Prio3PrepareState::decode_with_param(&(&vdaf, agg_id), bytes)?,
             ))
@@ -363,8 +364,8 @@ pub(crate) fn prio3_unshard<M: IntoIterator<Item = Vec<u8>>>(
             let agg_res = unshard!(vdaf, num_measurements, agg_shares)?;
             Ok(DapAggregateResult::U64(agg_res))
         }
-        Prio3Config::Histogram { buckets } => {
-            let vdaf = Prio3::new_histogram(2, buckets)?;
+        Prio3Config::Histogram { len } => {
+            let vdaf = Prio3::new_histogram(2, *len)?;
             let agg_res = unshard!(vdaf, num_measurements, agg_shares)?;
             Ok(DapAggregateResult::U128Vec(agg_res))
         }
diff --git a/daphne_worker/src/config.rs b/daphne_worker/src/config.rs
index 558873e..78c356d 100644
--- a/daphne_worker/src/config.rs
+++ b/daphne_worker/src/config.rs
@@ -924,6 +924,13 @@ impl<'srv> DaphneWorker<'srv> {
                 let len = length.parse().map_err(int_err)?;
                 VdafConfig::Prio3(Prio3Config::SumVec { bits, len })
             }
+            // NOTE: the VDAF-06 format is not supported yet
+            // https://datatracker.ietf.org/doc/html/draft-dcook-ppm-dap-interop-test-design-04#name-internal-test-add_task
+            // Issue tracked here: https://github.com/divergentdave/draft-dcook-ppm-dap-interop-test-design/issues/40
+            ("Prio3Histogram", Some(len), None) => {
+                let len = len.parse().map_err(int_err)?;
+                VdafConfig::Prio3(Prio3Config::Histogram { len })
+            }
             _ => return Err(int_err("command failed: unrecognized VDAF")),
         };
 


Test patch:
diff --git a/daphne/src/messages/mod_test.rs b/daphne/src/messages/mod_test.rs
index 0e3452d..5c7fc52 100644
--- a/daphne/src/messages/mod_test.rs
+++ b/daphne/src/messages/mod_test.rs
@@ -1,9 +1,6 @@
 // Copyright (c) 2022 Cloudflare, Inc. All rights reserved.
 // SPDX-License-Identifier: BSD-3-Clause
 
-use crate::messages::taskprov::{
-    DpConfig, QueryConfig, QueryConfigVar, TaskConfig, UrlBytes, VdafConfig, VdafTypeVar,
-};
 use crate::messages::{
     decode_base64url, decode_base64url_vec, encode_base64url, AggregateShareReq,
     AggregationJobContinueReq, AggregationJobId, AggregationJobInitReq, AggregationJobResp,
@@ -11,7 +8,6 @@ use crate::messages::{
     HpkeAeadId, HpkeCiphertext, HpkeConfig, HpkeKdfId, HpkeKemId, PartialBatchSelector, Report,
     ReportId, ReportMetadata, ReportShare, TaskId, Transition, TransitionVar,
 };
-use crate::taskprov::{compute_task_id, TaskprovVersion};
 use crate::{test_version, test_versions};
 use hpke_rs::HpkePublicKey;
 use paste::paste;
@@ -329,76 +325,81 @@ fn read_unsupported_hpke_config() {
     );
 }
 
-#[test]
-fn read_vdaf_config() {
-    let data = [
-        0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x01, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02,
-        0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x04, 0x04, 0x03,
-        0x02, 0x03,
-    ];
-
-    let buckets = vec![0x0102030404030201, 0x0202030404030202, 0x0302030404030203];
-    let vdaf_config = VdafConfig::get_decoded(&data).unwrap();
-    assert_eq!(
-        vdaf_config,
-        VdafConfig {
-            dp_config: DpConfig::None,
-            var: VdafTypeVar::Prio3Aes128Histogram { buckets },
-        }
-    );
-}
-
-#[test]
-fn read_task_config_taskprov_draft02() {
-    let data = [
-        0x02, 0x48, 0x69, 0x00, 0x0e, 0x00, 0x0c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
-        0x74, 0x65, 0x73, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80,
-        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x52, 0xf9,
-        0xa5, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x01, 0x02, 0x03, 0x04, 0x04, 0x03,
-        0x02, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x04, 0x04,
-        0x03, 0x02, 0x03,
-    ];
-
-    let buckets = vec![0x0102030404030201, 0x0202030404030202, 0x0302030404030203];
-    let task_config = TaskConfig::get_decoded_with_param(&TaskprovVersion::Draft02, &data).unwrap();
-    assert_eq!(
-        task_config,
-        TaskConfig {
-            task_info: "Hi".as_bytes().to_vec(),
-            aggregator_endpoints: vec![UrlBytes {
-                bytes: "https://test".as_bytes().to_vec()
-            }],
-            query_config: QueryConfig {
-                time_precision: 0x01,
-                max_batch_query_count: 128,
-                min_batch_size: 1024,
-                var: QueryConfigVar::FixedSize {
-                    max_batch_size: 2048
-                },
-            },
-            task_expiration: 0x6352f9a5,
-            vdaf_config: VdafConfig {
-                dp_config: DpConfig::None,
-                var: VdafTypeVar::Prio3Aes128Histogram { buckets },
-            },
-        }
-    );
-
-    assert_eq!(
-        compute_task_id(
-            TaskprovVersion::Draft02,
-            &task_config.get_encoded_with_param(&TaskprovVersion::Draft02)
-        )
-        .unwrap()
-        .to_hex(),
-        "2b585fcbb48c21fb5f05221a241fdd8cb9ebe99bd183d66326fcecd85fe06fd5",
-    );
-
-    assert_eq!(
-        task_config.get_encoded_with_param(&TaskprovVersion::Draft02),
-        &data
-    );
-}
+// NOTE: these test vectors are no longer valid, TaskProv doesn't match the VDAF-06 spec.
+// Tracking the issue here: https://github.com/wangshan/draft-wang-ppm-dap-taskprov/issues/33.
+// #[test]
+// fn read_vdaf_config() {
+//     let data = [
+//         0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x01, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02,
+//         0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x04, 0x04, 0x03,
+//         0x02, 0x03,
+//     ];
+
+//     // let buckets = vec![0x0102030404030201, 0x0202030404030202, 0x0302030404030203];
+//     let len_length: u8 = 1;
+//     let vdaf_config = VdafConfig::get_decoded(&data).unwrap();
+//     assert_eq!(
+//         vdaf_config,
+//         VdafConfig {
+//             dp_config: DpConfig::None,
+//             // var: VdafTypeVar::Prio3Aes128Histogram { buckets },
+//             var: VdafTypeVar::Prio3Aes128Histogram { len_length },
+//         }
+//     );
+// }
+
+// #[test]
+// fn read_task_config_taskprov_draft02() {
+//     let data = [
+//         0x02, 0x48, 0x69, 0x00, 0x0e, 0x00, 0x0c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
+//         0x74, 0x65, 0x73, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80,
+//         0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x52, 0xf9,
+//         0xa5, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x01, 0x02, 0x03, 0x04, 0x04, 0x03,
+//         0x02, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x04, 0x04,
+//         0x03, 0x02, 0x03,
+//     ];
+
+//     // let buckets = vec![0x0102030404030201, 0x0202030404030202, 0x0302030404030203];
+//     let len_length: u8 = 1;
+//     let task_config = TaskConfig::get_decoded_with_param(&TaskprovVersion::Draft02, &data).unwrap();
+//     assert_eq!(
+//         task_config,
+//         TaskConfig {
+//             task_info: "Hi".as_bytes().to_vec(),
+//             aggregator_endpoints: vec![UrlBytes {
+//                 bytes: "https://test".as_bytes().to_vec()
+//             }],
+//             query_config: QueryConfig {
+//                 time_precision: 0x01,
+//                 max_batch_query_count: 128,
+//                 min_batch_size: 1024,
+//                 var: QueryConfigVar::FixedSize {
+//                     max_batch_size: 2048
+//                 },
+//             },
+//             task_expiration: 0x6352f9a5,
+//             vdaf_config: VdafConfig {
+//                 dp_config: DpConfig::None,
+//                 var: VdafTypeVar::Prio3Aes128Histogram { len_length },
+//             },
+//         }
+//     );
+
+//     assert_eq!(
+//         compute_task_id(
+//             TaskprovVersion::Draft02,
+//             &task_config.get_encoded_with_param(&TaskprovVersion::Draft02)
+//         )
+//         .unwrap()
+//         .to_hex(),
+//         "2b585fcbb48c21fb5f05221a241fdd8cb9ebe99bd183d66326fcecd85fe06fd5",
+//     );
+
+//     assert_eq!(
+//         task_config.get_encoded_with_param(&TaskprovVersion::Draft02),
+//         &data
+//     );
+// }
 
 #[test]
 fn test_base64url() {
diff --git a/daphne/src/taskprov_test.rs b/daphne/src/taskprov_test.rs
index 8445590..5af6fad 100644
--- a/daphne/src/taskprov_test.rs
+++ b/daphne/src/taskprov_test.rs
@@ -69,9 +69,7 @@ fn test_resolve_advertised_task_config() {
         task_expiration: 0x6352f9a5,
         vdaf_config: VdafConfig {
             dp_config: DpConfig::None,
-            var: VdafTypeVar::Prio3Aes128Histogram {
-                buckets: vec![1, 2, 3],
-            },
+            var: VdafTypeVar::Prio3Aes128Histogram { len: 3 },
         },
     };
 
diff --git a/daphne/src/vdaf/prio3_test.rs b/daphne/src/vdaf/prio3_test.rs
index 62fd8b3..5e971b4 100644
--- a/daphne/src/vdaf/prio3_test.rs
+++ b/daphne/src/vdaf/prio3_test.rs
@@ -37,11 +37,9 @@ fn prepare_sum() {
 #[test]
 fn prepare_histogram() {
     test_prepare(
-        &Prio3Config::Histogram {
-            buckets: vec![0, 23, 9999999],
-        },
-        DapMeasurement::U64(1337),
-        DapAggregateResult::U128Vec(vec![0, 0, 1, 0]),
+        &Prio3Config::Histogram { len: 3 },
+        DapMeasurement::U64(2),
+        DapAggregateResult::U128Vec(vec![0, 0, 1]),
     )
     .unwrap();
 }