Provides privacy-preserving analytics on health metrics using homomorphic encryption and differential privacy. Enables secure aggregation of sensitive health data across multiple providers without exposing individual records.
initialize(env: Env, admin: Address, aggregator: Address, pub_key: PaillierPublicKey, priv_key: Option<PaillierPrivateKey>) -> Result<(), ContractError>
Initialize the analytics contract with admin credentials and encryption keys.
Parameters:
admin- Address with admin privilegesaggregator- Address authorized to aggregate and decrypt metricspub_key- Paillier public key for homomorphic operationspriv_key- Optional Paillier private key (stored if provided)
Returns: Result<(), ContractError>
Errors:
AlreadyInitialized- Contract has been initialized beforeNotInitialized- Required storage not initialized
Example:
let pub_key = PaillierPublicKey { /* ... */ };
let priv_key = Some(PaillierPrivateKey { /* ... */ });
client.initialize(&env, &admin, &aggregator, &pub_key, &priv_key)?;Encrypt a plaintext metric value using the Paillier public key.
Parameters:
m- Plaintext metric value to encrypt
Returns: Encrypted value (i128)
Example:
let metric_value = 42i128;
let encrypted = client.encrypt(&env, &metric_value);Add two encrypted values using homomorphic encryption properties. Result remains encrypted.
Parameters:
c1- First encrypted valuec2- Second encrypted value
Returns: Sum of encrypted values (encrypted)
Example:
let encrypted_sum = client.add_ciphertexts(&env, &encrypted_value_1, &encrypted_value_2);Decrypt a ciphertext. Only the registered aggregator can decrypt.
Parameters:
caller- Requesting address (must be aggregator)c- Encrypted value to decrypt
Returns: Decrypted plaintext value
Errors:
Unauthorized- Caller is not the aggregator or private key not available
Example:
let plaintext = client.decrypt(&env, &aggregator, &encrypted_value)?;aggregate_records(env: Env, caller: Address, kind: Symbol, dims: MetricDimensions, ciphertexts: Vec<i128>) -> Result<(), ContractError>
Aggregate encrypted metric records with differential privacy noise.
Parameters:
caller- Requesting address (must be aggregator)kind- Metric category (e.g.,symbol_short!("BP")for blood pressure)dims- Metric dimensions: region, age band, condition, time bucketciphertexts- Vector of encrypted metric values to aggregate
Returns: Result<(), ContractError>
Storage Update: Stores computed aggregate count and sum with Laplace noise applied for differential privacy.
Errors:
Unauthorized- Caller is not authorized
Example:
let dims = MetricDimensions {
region: Some(symbol_short!("US_WEST")),
age_band: Some(symbol_short!("50_60")),
condition: Some(symbol_short!("MYOPIA")),
time_bucket: 1707000000,
};
let encrypted_records = vec![encrypted_val_1, encrypted_val_2];
client.aggregate_records(&env, &caller, &symbol_short!("BP"), &dims, &encrypted_records)?;Retrieve aggregated metric statistics for given dimensions.
Parameters:
kind- Metric categorydims- Metric dimensions (region, age band, condition, time bucket)
Returns: MetricValue { count: i128, sum: i128 }
Example:
let metric = client.get_metric(&env, &symbol_short!("BP"), &dims);
println!("Count: {}, Sum: {}", metric.count, metric.sum);get_trend(env: Env, kind: Symbol, region: Option<Symbol>, age_band: Option<Symbol>, condition: Option<Symbol>, start_bucket: u64, end_bucket: u64) -> Vec<TrendPoint>
Retrieve time-series trend data across multiple time buckets.
Parameters:
kind- Metric categoryregion- Optional regional filterage_band- Optional age band filtercondition- Optional condition filterstart_bucket- Starting timestamp bucketend_bucket- Ending timestamp bucket (inclusive)
Returns: Vector of TrendPoint { time_bucket, value: MetricValue }
Example:
let trend = client.get_trend(&env, &symbol_short!("BP"), None, None, None, 1706000000, 1708000000);
for point in trend {
println!("Bucket {}: count={}, sum={}", point.time_bucket, point.value.count, point.value.sum);
}Retrieve the admin address.
Returns: Admin's Address
Retrieve the aggregator address.
Returns: Aggregator's Address
pub struct MetricDimensions {
pub region: Option<Symbol>, // Geographic region
pub age_band: Option<Symbol>, // Age bracket
pub condition: Option<Symbol>, // Medical condition
pub time_bucket: u64, // Timestamp bucket
}pub struct MetricValue {
pub count: i128, // Number of records
pub sum: i128, // Aggregated sum (with DP noise)
}pub struct TrendPoint {
pub time_bucket: u64, // Timestamp of this bucket
pub value: MetricValue, // Aggregated metrics
}Cryptographic keys for homomorphic encryption (structure defined in homomorphic.rs)
| Key | Symbol | Purpose |
|---|---|---|
ADMIN |
"ADMIN" |
Contract administrator address |
AGGREGATOR |
"AGGR" |
Authorized aggregator address |
PUB_KEY |
"PUB_KEY" |
Paillier public key |
PRIV_KEY |
"PRIV_KEY" |
Paillier private key (if stored) |
METRIC |
"METRIC" |
Aggregated metrics by dimensional key |
| Error | Code | Description |
|---|---|---|
AlreadyInitialized |
1 | Contract already initialized |
NotInitialized |
2 | Contract not yet initialized |
Unauthorized |
3 | Caller lacks required permissions |
No explicit events defined — audit trail maintained through persistent metric storage.
- Homomorphic Encryption Design
- Differential Privacy
- Storage Key Conventions
- Indexer Guide — for metric query patterns