Skip to content

Commit

Permalink
Add info fields to Hybrid Report Structs (#1469)
Browse files Browse the repository at this point in the history
Add info fields to Hybrid Report Structs and change encryption interfaces to no longer require info

More specifically:

Removes Serializable trait from HybridReport
Rewrites HybridInfo and related structs to be serializable and deserializable
Adds these info structs to report structs (as a struct for HybridReport, as bytes for EncryptedHybridReport)
Changes the encryption/decryption interfaces to not require an Info argument (grabbed from the report instead)
Changes TestHybridRecord to include info fields
  • Loading branch information
tyurek authored Dec 3, 2024
1 parent dca5be7 commit cf7efd4
Show file tree
Hide file tree
Showing 9 changed files with 685 additions and 290 deletions.
20 changes: 17 additions & 3 deletions ipa-core/src/cli/csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,25 @@ impl Serializer for crate::test_fixture::hybrid::TestHybridRecord {
crate::test_fixture::hybrid::TestHybridRecord::TestImpression {
match_key,
breakdown_key,
key_id,
helper_origin,
} => {
write!(buf, "i,{match_key},{breakdown_key}")?;
write!(
buf,
"i,{match_key},{breakdown_key},{key_id},{helper_origin}"
)?;
}
crate::test_fixture::hybrid::TestHybridRecord::TestConversion { match_key, value } => {
write!(buf, "c,{match_key},{value}")?;
crate::test_fixture::hybrid::TestHybridRecord::TestConversion {
match_key,
value,
key_id,
helper_origin,
conversion_site_domain,
timestamp,
epsilon,
sensitivity,
} => {
write!(buf, "c,{match_key},{value},{key_id},{helper_origin},{conversion_site_domain},{timestamp},{epsilon},{sensitivity}")?;
}
}

Expand Down
99 changes: 73 additions & 26 deletions ipa-core/src/cli/playbook/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,34 +59,81 @@ impl InputItem for TestRawDataRecord {

impl InputItem for TestHybridRecord {
fn from_str(s: &str) -> Self {
if let [event_type, match_key, number] = s.splitn(3, ',').collect::<Vec<_>>()[..] {
let match_key: u64 = match_key
.parse()
.unwrap_or_else(|e| panic!("Expected an u64, got {match_key}: {e}"));

let number: u32 = number
.parse()
.unwrap_or_else(|e| panic!("Expected an u32, got {number}: {e}"));

match event_type {
"i" => TestHybridRecord::TestImpression {
match_key,
breakdown_key: number,
},

"c" => TestHybridRecord::TestConversion {
match_key,
value: number,
},
_ => panic!(
"{}",
format!(
let event_type = s.chars().nth(0).unwrap();
match event_type {
'i' => {
if let [_, match_key, number, key_id, helper_origin] =
s.splitn(5, ',').collect::<Vec<_>>()[..]
{
let match_key: u64 = match_key
.parse()
.unwrap_or_else(|e| panic!("Expected a u64, got {match_key}: {e}"));

let number: u32 = number
.parse()
.unwrap_or_else(|e| panic!("Expected a u32, got {number}: {e}"));

let key_id: u8 = key_id
.parse()
.unwrap_or_else(|e| panic!("Expected a u8, got {key_id}: {e}"));
TestHybridRecord::TestImpression {
match_key,
breakdown_key: number,
key_id,
helper_origin: helper_origin.to_string(),
}
} else {
panic!("{s} is not a valid {}", type_name::<Self>())
}
}

'c' => {
if let [_, match_key, number, key_id, helper_origin, conversion_site_domain, timestamp, epsilon, sensitivity] =
s.splitn(9, ',').collect::<Vec<_>>()[..]
{
let match_key: u64 = match_key
.parse()
.unwrap_or_else(|e| panic!("Expected a u64, got {match_key}: {e}"));

let number: u32 = number
.parse()
.unwrap_or_else(|e| panic!("Expected a u32, got {number}: {e}"));

let key_id: u8 = key_id
.parse()
.unwrap_or_else(|e| panic!("Expected a u8, got {key_id}: {e}"));

let timestamp: u64 = timestamp
.parse()
.unwrap_or_else(|e| panic!("Expected a u64, got {timestamp}: {e}"));

let epsilon: f64 = epsilon
.parse()
.unwrap_or_else(|e| panic!("Expected an f64, got {epsilon}: {e}"));

let sensitivity: f64 = sensitivity
.parse()
.unwrap_or_else(|e| panic!("Expected an f64, got {sensitivity}: {e}"));
TestHybridRecord::TestConversion {
match_key,
value: number,
key_id,
helper_origin: helper_origin.to_string(),
conversion_site_domain: conversion_site_domain.to_string(),
timestamp,
epsilon,
sensitivity,
}
} else {
panic!("{s} is not a valid {}", type_name::<Self>())
}
}
_ => panic!(
"{}",
format!(
"Invalid input. Rows should start with 'i' or 'c'. Did not expect {event_type}"
)
),
}
} else {
panic!("{s} is not a valid {}", type_name::<Self>())
),
}
}
}
Expand Down
63 changes: 63 additions & 0 deletions ipa-core/src/protocol/hybrid/agg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,65 +193,128 @@ pub mod test {
const SHARD1_MKS: [u64; 7] = [12345, 12345, 34567, 34567, 78901, 78901, 78901];
const SHARD2_MKS: [u64; 7] = [23456, 23456, 45678, 56789, 67890, 67890, 67890];

#[allow(clippy::too_many_lines)]
fn get_records() -> Vec<TestHybridRecord> {
let helper_origin = "HELPER_ORIGIN".to_string();
let conversion_site_domain = "meta.com".to_string();
let shard1_records = [
TestHybridRecord::TestImpression {
match_key: SHARD1_MKS[0],
breakdown_key: 45,
key_id: 0,
helper_origin: helper_origin.clone(),
},
TestHybridRecord::TestConversion {
match_key: SHARD1_MKS[1],
value: 1,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 102,
epsilon: 0.0,
sensitivity: 0.0,
}, // attributed
TestHybridRecord::TestConversion {
match_key: SHARD1_MKS[2],
value: 3,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 103,
epsilon: 0.0,
sensitivity: 0.0,
},
TestHybridRecord::TestConversion {
match_key: SHARD1_MKS[3],
value: 4,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 104,
epsilon: 0.0,
sensitivity: 0.0,
}, // not attibuted, but duplicated conversion. will land in breakdown_key 0
TestHybridRecord::TestImpression {
match_key: SHARD1_MKS[4],
breakdown_key: 1,
key_id: 0,
helper_origin: helper_origin.clone(),
}, // duplicated impression with same match_key
TestHybridRecord::TestImpression {
match_key: SHARD1_MKS[4],
breakdown_key: 2,
key_id: 0,
helper_origin: helper_origin.clone(),
}, // duplicated impression with same match_key
TestHybridRecord::TestConversion {
match_key: SHARD1_MKS[5],
value: 7,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 105,
epsilon: 0.0,
sensitivity: 0.0,
}, // removed
];
let shard2_records = [
TestHybridRecord::TestImpression {
match_key: SHARD2_MKS[0],
breakdown_key: 56,
key_id: 0,
helper_origin: helper_origin.clone(),
},
TestHybridRecord::TestConversion {
match_key: SHARD2_MKS[1],
value: 2,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 100,
epsilon: 0.0,
sensitivity: 0.0,
}, // attributed
TestHybridRecord::TestImpression {
match_key: SHARD2_MKS[2],
breakdown_key: 78,
key_id: 0,
helper_origin: helper_origin.clone(),
}, // NOT attributed
TestHybridRecord::TestConversion {
match_key: SHARD2_MKS[3],
value: 5,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 101,
epsilon: 0.0,
sensitivity: 0.0,
}, // NOT attributed
TestHybridRecord::TestImpression {
match_key: SHARD2_MKS[4],
breakdown_key: 90,
key_id: 0,
helper_origin: helper_origin.clone(),
}, // attributed twice, removed
TestHybridRecord::TestConversion {
match_key: SHARD2_MKS[5],
value: 6,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 102,
epsilon: 0.0,
sensitivity: 0.0,
}, // attributed twice, removed
TestHybridRecord::TestConversion {
match_key: SHARD2_MKS[6],
value: 7,
key_id: 0,
helper_origin: helper_origin.clone(),
conversion_site_domain: conversion_site_domain.clone(),
timestamp: 103,
epsilon: 0.0,
sensitivity: 0.0,
}, // attributed twice, removed
];

Expand Down
25 changes: 25 additions & 0 deletions ipa-core/src/protocol/hybrid/oprf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ mod test {
};

#[test]
#[allow(clippy::too_many_lines)]
fn hybrid_oprf() {
run(|| async {
const SHARDS: usize = 2;
Expand All @@ -229,26 +230,50 @@ mod test {
TestHybridRecord::TestImpression {
match_key: 12345,
breakdown_key: 2,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
},
TestHybridRecord::TestImpression {
match_key: 68362,
breakdown_key: 1,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
},
TestHybridRecord::TestConversion {
match_key: 12345,
value: 5,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
conversion_site_domain: "meta.com".to_string(),
timestamp: 100,
epsilon: 0.0,
sensitivity: 0.0,
},
TestHybridRecord::TestConversion {
match_key: 68362,
value: 2,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
conversion_site_domain: "meta.com".to_string(),
timestamp: 102,
epsilon: 0.0,
sensitivity: 0.0,
},
TestHybridRecord::TestImpression {
match_key: 68362,
breakdown_key: 1,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
},
TestHybridRecord::TestConversion {
match_key: 68362,
value: 7,
key_id: 0,
helper_origin: "HELPER_ORIGIN".to_string(),
conversion_site_domain: "meta.com".to_string(),
timestamp: 104,
epsilon: 0.0,
sensitivity: 0.0,
},
];

Expand Down
Loading

0 comments on commit cf7efd4

Please sign in to comment.