Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

taskprov: Enable Prio3SumVecField64MultiproofHmacSha256Aes128 in draft09 #447

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion daphne/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ impl DapTaskParameters {
task_expiration: now + 86400 * 14, // expires in two weeks
vdaf_config: messages::taskprov::VdafConfig {
dp_config: messages::taskprov::DpConfig::None,
var: messages::taskprov::VdafTypeVar::Prio2 { dimension: 10 },
var: (&self.vdaf).try_into()?,
},
};

Expand Down
25 changes: 0 additions & 25 deletions daphne/src/messages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,31 +1288,6 @@ fn decode_u16_prefixed<O>(
Ok(decoded)
}

fn encode_u16_item_for_version<E: ParameterizedEncode<DapVersion>>(
bytes: &mut Vec<u8>,
version: DapVersion,
item: &E,
) {
match version {
DapVersion::DraftLatest => encode_u16_prefixed(version, bytes, |version, bytes| {
item.encode_with_param(&version, bytes);
}),
DapVersion::Draft02 => item.encode_with_param(&version, bytes),
}
}

fn decode_u16_item_for_version<D: ParameterizedDecode<DapVersion>>(
version: DapVersion,
bytes: &mut Cursor<&[u8]>,
) -> Result<D, CodecError> {
match version {
DapVersion::DraftLatest => decode_u16_prefixed(version, bytes, |version, inner| {
D::decode_with_param(&version, inner)
}),
DapVersion::Draft02 => D::decode_with_param(&version, bytes),
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
159 changes: 129 additions & 30 deletions daphne/src/messages/taskprov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//! draft-wang-ppm-dap-taskprov: Messages for the taskrpov extension for DAP.

use crate::messages::{
decode_u16_bytes, decode_u16_item_for_version, encode_u16_bytes, encode_u16_item_for_version,
Duration, Time, QUERY_TYPE_FIXED_SIZE, QUERY_TYPE_TIME_INTERVAL,
decode_u16_bytes, encode_u16_bytes, Duration, Time, QUERY_TYPE_FIXED_SIZE,
QUERY_TYPE_TIME_INTERVAL,
};
use crate::DapVersion;
use prio::codec::{
Expand All @@ -15,32 +15,61 @@ use prio::codec::{
use serde::{Deserialize, Serialize};
use std::io::Cursor;

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;

// Differential privacy mechanism types.
const DP_MECHANISM_NONE: u8 = 0x01;

/// A VDAF type along with its type-specific data.
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)]
pub enum VdafTypeVar {
Prio2 { dimension: u32 },
NotImplemented { typ: u32, param: Vec<u8> },
Prio2 {
dimension: u32,
},
Prio3SumVecField64MultiproofHmacSha256Aes128 {
bits: u8,
length: u32,
chunk_length: u32,
num_proofs: u8,
},
NotImplemented {
typ: u32,
param: Vec<u8>,
},
}

impl ParameterizedEncode<DapVersion> for VdafTypeVar {
fn encode_with_param(&self, version: &DapVersion, bytes: &mut Vec<u8>) {
match self {
Self::Prio2 { dimension } => {
VDAF_TYPE_PRIO2.encode(bytes);
encode_u16_item_for_version(bytes, *version, dimension);
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
dimension.encode(inner);
});
}
Self::Prio3SumVecField64MultiproofHmacSha256Aes128 {
bits,
length,
chunk_length,
num_proofs,
} => {
VDAF_TYPE_PRIO3_SUM_VEC_FIELD64_MULTIPROOF_HMAC_SHA256_AES128.encode(bytes);
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
bits.encode(inner);
length.encode(inner);
chunk_length.encode(inner);
num_proofs.encode(inner);
});
}
Self::NotImplemented { typ, param } => {
typ.encode(bytes);
match version {
DapVersion::DraftLatest => encode_u16_bytes(bytes, param),
DapVersion::Draft02 => bytes.extend_from_slice(param),
}
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
inner.extend_from_slice(param);
});
}
}
}
Expand All @@ -53,9 +82,23 @@ impl ParameterizedDecode<DapVersion> for VdafTypeVar {
) -> Result<Self, CodecError> {
let vdaf_type = u32::decode(bytes)?;
match (version, vdaf_type) {
(.., VDAF_TYPE_PRIO2) => Ok(Self::Prio2 {
dimension: decode_u16_item_for_version(*version, bytes)?,
}),
(.., VDAF_TYPE_PRIO2) => {
taskprov_decode_u16_prefixed(*version, bytes, |_version, inner| {
Ok(Self::Prio2 {
dimension: u32::decode(inner)?,
})
})
}
(.., VDAF_TYPE_PRIO3_SUM_VEC_FIELD64_MULTIPROOF_HMAC_SHA256_AES128) => {
taskprov_decode_u16_prefixed(*version, bytes, |_version, inner| {
Ok(Self::Prio3SumVecField64MultiproofHmacSha256Aes128 {
bits: u8::decode(inner)?,
length: u32::decode(inner)?,
chunk_length: u32::decode(inner)?,
num_proofs: u8::decode(inner)?,
})
})
}
(DapVersion::DraftLatest, ..) => Ok(Self::NotImplemented {
typ: vdaf_type,
param: decode_u16_bytes(bytes)?,
Expand All @@ -79,15 +122,14 @@ impl ParameterizedEncode<DapVersion> for DpConfig {
match self {
Self::None => {
DP_MECHANISM_NONE.encode(bytes);
encode_u16_item_for_version(bytes, *version, &());
taskprov_encode_u16_prefixed(*version, bytes, |_, _| ());
}

Self::NotImplemented { typ, param } => {
typ.encode(bytes);
match version {
DapVersion::DraftLatest => encode_u16_bytes(bytes, param),
DapVersion::Draft02 => bytes.extend_from_slice(param),
}
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
inner.extend_from_slice(param);
});
}
}
}
Expand All @@ -101,7 +143,9 @@ impl ParameterizedDecode<DapVersion> for DpConfig {
let dp_mechanism = u8::decode(bytes)?;
match (version, dp_mechanism) {
(.., DP_MECHANISM_NONE) => {
decode_u16_item_for_version::<()>(*version, bytes)?;
taskprov_decode_u16_prefixed::<()>(*version, bytes, |_version, inner| {
<()>::decode(inner)
})?;
Ok(Self::None)
}
(DapVersion::DraftLatest, ..) => Ok(Self::NotImplemented {
Expand Down Expand Up @@ -207,18 +251,19 @@ impl ParameterizedEncode<DapVersion> for QueryConfig {
match &self.var {
QueryConfigVar::TimeInterval => {
QUERY_TYPE_TIME_INTERVAL.encode(bytes);
encode_u16_item_for_version(bytes, *version, &());
taskprov_encode_u16_prefixed(*version, bytes, |_, _| ());
}
QueryConfigVar::FixedSize { max_batch_size } => {
QUERY_TYPE_FIXED_SIZE.encode(bytes);
encode_u16_item_for_version(bytes, *version, max_batch_size);
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
max_batch_size.encode(inner);
});
}
QueryConfigVar::NotImplemented { typ, param } => {
typ.encode(bytes);
match version {
DapVersion::DraftLatest => encode_u16_bytes(bytes, param),
DapVersion::Draft02 => bytes.extend_from_slice(param),
}
taskprov_encode_u16_prefixed(*version, bytes, |_version, inner| {
inner.extend_from_slice(param);
});
}
}
}
Expand All @@ -239,12 +284,18 @@ impl ParameterizedDecode<DapVersion> for QueryConfig {
let query_type = query_type.unwrap_or(u8::decode(bytes)?);
let var = match (version, query_type) {
(.., QUERY_TYPE_TIME_INTERVAL) => {
decode_u16_item_for_version::<()>(*version, bytes)?;
taskprov_decode_u16_prefixed::<()>(*version, bytes, |_version, inner| {
<()>::decode(inner)
})?;
QueryConfigVar::TimeInterval
}
(.., QUERY_TYPE_FIXED_SIZE) => QueryConfigVar::FixedSize {
max_batch_size: decode_u16_item_for_version(*version, bytes)?,
},
(.., QUERY_TYPE_FIXED_SIZE) => {
taskprov_decode_u16_prefixed(*version, bytes, |_version, inner| {
Ok(QueryConfigVar::FixedSize {
max_batch_size: u32::decode(inner)?,
})
})?
}
(DapVersion::DraftLatest, ..) => QueryConfigVar::NotImplemented {
typ: query_type,
param: decode_u16_bytes(bytes)?,
Expand Down Expand Up @@ -318,6 +369,30 @@ impl ParameterizedDecode<DapVersion> for TaskConfig {
}
}

fn taskprov_encode_u16_prefixed(
version: DapVersion,
bytes: &mut Vec<u8>,
e: impl Fn(DapVersion, &mut Vec<u8>),
) {
match version {
DapVersion::DraftLatest => encode_u16_prefixed(version, bytes, e),
// draft02 compatibility: No length prefix is used.
DapVersion::Draft02 => e(version, bytes),
}
}

fn taskprov_decode_u16_prefixed<O>(
version: DapVersion,
bytes: &mut Cursor<&[u8]>,
d: impl Fn(DapVersion, &mut Cursor<&[u8]>) -> Result<O, CodecError>,
) -> Result<O, CodecError> {
match version {
DapVersion::DraftLatest => decode_u16_prefixed(version, bytes, d),
// draft02 compatibility: No length prefix is used.
DapVersion::Draft02 => d(version, bytes),
}
}

#[cfg(test)]
mod tests {
use crate::test_versions;
Expand Down Expand Up @@ -443,7 +518,7 @@ mod tests {
.is_err());
}

fn roundtrip_vdaf_config(version: DapVersion) {
fn roundtrip_vdaf_config_prio2(version: DapVersion) {
let vdaf_config = VdafConfig {
dp_config: DpConfig::None,
var: VdafTypeVar::Prio2 { dimension: 1337 },
Expand All @@ -458,7 +533,31 @@ mod tests {
);
}

test_versions! { roundtrip_vdaf_config }
test_versions! { roundtrip_vdaf_config_prio2 }

fn roundtrip_vdaf_config_prio3_sum_vec_field64_multiproof_hmac_sha256_aes128(
version: DapVersion,
) {
let vdaf_config = VdafConfig {
dp_config: DpConfig::None,
var: VdafTypeVar::Prio3SumVecField64MultiproofHmacSha256Aes128 {
bits: 23,
length: 1337,
chunk_length: 42,
num_proofs: 99,
},
};
assert_eq!(
VdafConfig::get_decoded_with_param(
&version,
&vdaf_config.get_encoded_with_param(&version)
)
.unwrap(),
vdaf_config
);
}

test_versions! { roundtrip_vdaf_config_prio3_sum_vec_field64_multiproof_hmac_sha256_aes128 }

#[test]
fn roundtrip_vdaf_config_not_implemented_draft09() {
Expand Down
35 changes: 32 additions & 3 deletions daphne/src/roles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1752,14 +1752,19 @@ mod test {

async_test_versions! { e2e_fixed_size }

async fn e2e_taskprov(version: DapVersion) {
async fn e2e_taskprov(
version: DapVersion,
vdaf_config: VdafConfig,
test_measurement: DapMeasurement,
) {
let t = Test::new(version);

let (task_config, task_id, taskprov_advertisement, taskprov_report_extension_payload) =
DapTaskParameters {
version,
min_batch_size: 1,
query: DapQueryConfig::FixedSize { max_batch_size: 2 },
vdaf: vdaf_config,
..Default::default()
}
.to_config_with_taskprov(
Expand Down Expand Up @@ -1792,7 +1797,7 @@ mod test {
&hpke_config_list,
t.now,
&task_id,
DapMeasurement::U32Vec(vec![1; 10]),
test_measurement.clone(),
vec![Extension::Taskprov {
draft02_payload: match version {
DapVersion::DraftLatest => None,
Expand Down Expand Up @@ -1850,7 +1855,31 @@ mod test {
});
}

async_test_versions! { e2e_taskprov }
async fn e2e_taskprov_prio2(version: DapVersion) {
e2e_taskprov(
version,
VdafConfig::Prio2 { dimension: 10 },
DapMeasurement::U32Vec(vec![1; 10]),
)
.await;
}

async_test_versions! { e2e_taskprov_prio2 }

#[tokio::test]
async fn e2e_taskprov_prio3_sum_vec_field64_multiproof_hmac_sha256_aes128_draft09() {
e2e_taskprov(
DapVersion::DraftLatest,
VdafConfig::Prio3(Prio3Config::SumVecField64MultiproofHmacSha256Aes128 {
bits: 1,
length: 10,
chunk_length: 2,
num_proofs: 4,
}),
DapMeasurement::U64Vec(vec![1; 10]),
)
.await;
}

fn early_metadata_checks(version: DapVersion) {
let t = Test::new(version);
Expand Down
Loading