use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdvancedPrivacyConfig {
pub epsilon: f64,
pub delta: f64,
pub mechanism: PrivacyMechanism,
pub privacy_model: PrivacyModel,
pub composition_method: CompositionMethod,
pub adaptive_budgeting: bool,
pub amplification_config: PrivacyAmplificationConfig,
pub noise_config: NoiseDistributionConfig,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrivacyMechanism {
Gaussian,
Laplace,
Exponential,
AboveThreshold,
SparseVector,
PATE,
RenyiDP,
ZCDP,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrivacyModel {
LocalDP,
CentralDP,
ShuffledModel,
HybridModel,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompositionMethod {
Basic,
Advanced,
Optimal,
RenyiComposition,
ZCDPComposition,
PLDTracking,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrivacyAmplificationConfig {
pub subsampling_ratio: f64,
pub shuffling_enabled: bool,
pub secure_aggregation_amplification: bool,
pub sampling_method: SamplingMethod,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SamplingMethod {
UniformRandom,
Poisson,
Systematic,
Stratified,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NoiseDistributionConfig {
pub noise_multiplier: f64,
pub clipping_norm: f64,
pub adaptive_clipping: bool,
pub per_layer_scaling: bool,
pub correlated_noise: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrivacyAccountingConfig {
pub accounting_method: PrivacyAccountingMethod,
pub max_epsilon: f64,
pub max_delta: f64,
pub tracking_granularity: TrackingGranularity,
pub composition_tracking: bool,
pub pld_params: PLDParameters,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrivacyAccountingMethod {
BasicComposition,
MomentsAccountant,
RenyiAccountant,
PrivacyLossDistribution,
ZCDPAccountant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TrackingGranularity {
PerRound,
PerParticipant,
PerQuery,
Global,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PLDParameters {
pub discretization_interval: f64,
pub truncation_bound: f64,
pub pessimistic_estimate: bool,
pub tail_bound_approximation: bool,
}
impl Default for AdvancedPrivacyConfig {
fn default() -> Self {
Self {
epsilon: 1.0,
delta: 1e-5,
mechanism: PrivacyMechanism::Gaussian,
privacy_model: PrivacyModel::CentralDP,
composition_method: CompositionMethod::Advanced,
adaptive_budgeting: true,
amplification_config: PrivacyAmplificationConfig::default(),
noise_config: NoiseDistributionConfig::default(),
}
}
}
impl Default for PrivacyAmplificationConfig {
fn default() -> Self {
Self {
subsampling_ratio: 0.01,
shuffling_enabled: true,
secure_aggregation_amplification: true,
sampling_method: SamplingMethod::UniformRandom,
}
}
}
impl Default for NoiseDistributionConfig {
fn default() -> Self {
Self {
noise_multiplier: 1.0,
clipping_norm: 1.0,
adaptive_clipping: true,
per_layer_scaling: false,
correlated_noise: false,
}
}
}
impl Default for PrivacyAccountingConfig {
fn default() -> Self {
Self {
accounting_method: PrivacyAccountingMethod::MomentsAccountant,
max_epsilon: 10.0,
max_delta: 1e-5,
tracking_granularity: TrackingGranularity::PerRound,
composition_tracking: true,
pld_params: PLDParameters::default(),
}
}
}
impl Default for PLDParameters {
fn default() -> Self {
Self {
discretization_interval: 1e-3,
truncation_bound: 1e2,
pessimistic_estimate: false,
tail_bound_approximation: true,
}
}
}
#[derive(Debug, Clone)]
pub struct PrivacyBudgetTracker {
pub epsilon_consumed: f64,
pub delta_consumed: f64,
pub max_epsilon: f64,
pub max_delta: f64,
pub accounting_method: PrivacyAccountingMethod,
pub epsilon_history: Vec<f64>,
pub delta_history: Vec<f64>,
}
impl PrivacyBudgetTracker {
pub fn new(max_epsilon: f64, max_delta: f64, accounting_method: PrivacyAccountingMethod) -> Self {
Self {
epsilon_consumed: 0.0,
delta_consumed: 0.0,
max_epsilon,
max_delta,
accounting_method,
epsilon_history: Vec::new(),
delta_history: Vec::new(),
}
}
pub fn can_consume(&self, epsilon: f64, delta: f64) -> bool {
self.epsilon_consumed + epsilon <= self.max_epsilon &&
self.delta_consumed + delta <= self.max_delta
}
pub fn consume(&mut self, epsilon: f64, delta: f64) -> Result<(), String> {
if !self.can_consume(epsilon, delta) {
return Err("Privacy budget exceeded".to_string());
}
self.epsilon_consumed += epsilon;
self.delta_consumed += delta;
self.epsilon_history.push(epsilon);
self.delta_history.push(delta);
Ok(())
}
pub fn remaining_budget(&self) -> (f64, f64) {
(
self.max_epsilon - self.epsilon_consumed,
self.max_delta - self.delta_consumed,
)
}
pub fn reset(&mut self) {
self.epsilon_consumed = 0.0;
self.delta_consumed = 0.0;
self.epsilon_history.clear();
self.delta_history.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_privacy_config_default() {
let config = AdvancedPrivacyConfig::default();
assert_eq!(config.epsilon, 1.0);
assert_eq!(config.delta, 1e-5);
assert_eq!(config.mechanism, PrivacyMechanism::Gaussian);
assert_eq!(config.privacy_model, PrivacyModel::CentralDP);
}
#[test]
fn test_privacy_budget_tracker() {
let mut tracker = PrivacyBudgetTracker::new(2.0, 1e-5, PrivacyAccountingMethod::BasicComposition);
assert!(tracker.can_consume(1.0, 5e-6));
assert!(tracker.consume(1.0, 5e-6).is_ok());
assert_eq!(tracker.epsilon_consumed, 1.0);
assert_eq!(tracker.delta_consumed, 5e-6);
assert!(!tracker.can_consume(1.5, 1e-5));
assert!(tracker.consume(1.5, 1e-5).is_err());
assert!(tracker.can_consume(1.0, 5e-6));
assert!(tracker.consume(1.0, 5e-6).is_ok());
let (remaining_eps, remaining_delta) = tracker.remaining_budget();
assert_eq!(remaining_eps, 0.0);
assert_eq!(remaining_delta, 0.0);
}
#[test]
fn test_privacy_mechanism_serialization() {
let mechanism = PrivacyMechanism::Gaussian;
let serialized = serde_json::to_string(&mechanism).expect("Operation failed");
let deserialized: PrivacyMechanism = serde_json::from_str(&serialized).expect("Operation failed");
assert_eq!(mechanism, deserialized);
}
#[test]
fn test_privacy_amplification_config() {
let config = PrivacyAmplificationConfig::default();
assert_eq!(config.subsampling_ratio, 0.01);
assert!(config.shuffling_enabled);
assert!(config.secure_aggregation_amplification);
assert_eq!(config.sampling_method, SamplingMethod::UniformRandom);
}
#[test]
fn test_composition_methods() {
let methods = [
CompositionMethod::Basic,
CompositionMethod::Advanced,
CompositionMethod::Optimal,
CompositionMethod::RenyiComposition,
CompositionMethod::ZCDPComposition,
CompositionMethod::PLDTracking,
];
for method in &methods {
let serialized = serde_json::to_string(method).expect("Operation failed");
let deserialized: CompositionMethod = serde_json::from_str(&serialized).expect("Operation failed");
assert_eq!(*method, deserialized);
}
}
}