Skip to content

Commit

Permalink
Implement VDAF-06 histogram format, upgrade libprio to 0.13.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tholop authored and cjpatton committed Jul 14, 2023
1 parent 0785e28 commit dbd506d
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 128 deletions.
40 changes: 20 additions & 20 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 2 additions & 4 deletions daphne/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ pub enum Prio3Config {

/// A histogram for estimating the distribution of 64-bit, unsigned integers using pre-defined
/// bucket boundaries.
Histogram { buckets: Vec<u64> },
Histogram { len: usize },

/// The sum of 64-bit, unsigned integers. Each measurement is an integer in range `[0,
/// 2^bits)`.
Expand All @@ -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})"),
}
Expand Down
149 changes: 75 additions & 74 deletions daphne/src/messages/mod_test.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
// 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,
BatchId, BatchSelector, CollectionJobId, DapVersion, Draft02AggregationJobId, Extension,
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;
Expand Down Expand Up @@ -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
// 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() {
Expand Down
12 changes: 6 additions & 6 deletions daphne/src/messages/taskprov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -54,7 +54,7 @@ impl KeyType for VdafType {
pub enum VdafTypeVar {
Prio3Aes128Count,
Prio3Aes128Sum { bit_length: u8 },
Prio3Aes128Histogram { buckets: Vec<u64> },
Prio3Aes128Histogram { len_length: u8 },
Poplar1Aes128 { bit_length: u16 },
NotImplemented(u32),
}
Expand All @@ -67,9 +67,9 @@ impl Encode for VdafTypeVar {
VDAF_TYPE_PRIO3_AES128_SUM.encode(bytes);
bit_length.encode(bytes);
}
VdafTypeVar::Prio3Aes128Histogram { buckets } => {
VdafTypeVar::Prio3Aes128Histogram { len_length } => {
VDAF_TYPE_PRIO3_AES128_HISTOGRAM.encode(bytes);
encode_u24_items(bytes, &(), buckets);
len_length.encode(bytes);
}
VdafTypeVar::Poplar1Aes128 { bit_length } => {
VDAF_TYPE_POPLAR1_AES128.encode(bytes);
Expand All @@ -91,7 +91,7 @@ impl Decode for VdafTypeVar {
bit_length: u8::decode(bytes)?,
}),
VDAF_TYPE_PRIO3_AES128_HISTOGRAM => Ok(Self::Prio3Aes128Histogram {
buckets: decode_u24_items(&(), bytes)?,
len_length: u8::decode(bytes)?,
}),
VDAF_TYPE_POPLAR1_AES128 => Ok(Self::Poplar1Aes128 {
bit_length: u16::decode(bytes)?,
Expand Down
6 changes: 4 additions & 2 deletions daphne/src/taskprov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_length } => {
VdafConfig::Prio3(Prio3Config::Histogram {
len: len_length.into(),
})
}
VdafTypeVar::Prio3Aes128Sum { bit_length } => VdafConfig::Prio3(Prio3Config::Sum {
bits: bit_length.into(),
Expand Down
4 changes: 1 addition & 3 deletions daphne/src/taskprov_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_length: 1 },
},
};

Expand Down
Loading

0 comments on commit dbd506d

Please sign in to comment.