Initial commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
//! Privacy budget management and accounting
|
||||
|
||||
use crate::error::{FederatedError, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
use tracing::info;
|
||||
|
||||
/// Privacy budget for differential privacy
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PrivacyBudget {
|
||||
pub epsilon: f64,
|
||||
pub delta: f64,
|
||||
}
|
||||
|
||||
impl PrivacyBudget {
|
||||
pub fn new(epsilon: f64) -> Self {
|
||||
Self {
|
||||
epsilon,
|
||||
delta: 1e-5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Privacy accountant for tracking budget consumption
|
||||
#[derive(Debug)]
|
||||
pub struct PrivacyAccountant {
|
||||
total_budget: PrivacyBudget,
|
||||
consumed_budget: PrivacyBudget,
|
||||
transaction_history: VecDeque<PrivacyTransaction>,
|
||||
max_history_size: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PrivacyTransaction {
|
||||
pub epsilon_consumed: f64,
|
||||
pub delta_consumed: f64,
|
||||
pub timestamp: chrono::DateTime<chrono::Utc>,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
impl PrivacyAccountant {
|
||||
pub fn new(total_budget: PrivacyBudget) -> Self {
|
||||
Self {
|
||||
total_budget,
|
||||
consumed_budget: PrivacyBudget {
|
||||
epsilon: 0.0,
|
||||
delta: 0.0,
|
||||
},
|
||||
transaction_history: VecDeque::new(),
|
||||
max_history_size: 1000,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn consume(&mut self, epsilon: f64, delta: f64, description: String) -> Result<()> {
|
||||
if self.consumed_budget.epsilon + epsilon > self.total_budget.epsilon {
|
||||
return Err(FederatedError::PrivacyBudgetExceeded {
|
||||
remaining: self.total_budget.epsilon - self.consumed_budget.epsilon,
|
||||
requested: epsilon,
|
||||
});
|
||||
}
|
||||
|
||||
self.consumed_budget.epsilon += epsilon;
|
||||
self.consumed_budget.delta += delta;
|
||||
|
||||
let transaction = PrivacyTransaction {
|
||||
epsilon_consumed: epsilon,
|
||||
delta_consumed: delta,
|
||||
timestamp: chrono::Utc::now(),
|
||||
description: description.clone(),
|
||||
};
|
||||
|
||||
self.transaction_history.push_back(transaction);
|
||||
|
||||
if self.transaction_history.len() > self.max_history_size {
|
||||
self.transaction_history.pop_front();
|
||||
}
|
||||
|
||||
info!(
|
||||
"🔒 Privacy budget consumed: ε={:.6}, δ={:.2e} ({})",
|
||||
epsilon, delta, description
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remaining_budget(&self) -> PrivacyBudget {
|
||||
PrivacyBudget {
|
||||
epsilon: (self.total_budget.epsilon - self.consumed_budget.epsilon).max(0.0),
|
||||
delta: (self.total_budget.delta - self.consumed_budget.delta).max(0.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn budget_utilization(&self) -> f64 {
|
||||
self.consumed_budget.epsilon / self.total_budget.epsilon
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user