Add runnable Exp3 timing-leak simulation harness with CLI and tests#70
Add runnable Exp3 timing-leak simulation harness with CLI and tests#70
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b476885b18
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fn accuracy_with_threshold(bits: &[u8], times: &[f64], threshold: f64) -> f64 { | ||
| let mut correct = 0usize; | ||
| for (b, t) in bits.iter().zip(times) { | ||
| let pred = if *t >= threshold { 1u8 } else { 0u8 }; |
There was a problem hiding this comment.
Learn threshold polarity before reporting attack accuracy
The attacker model only searches for a threshold and hard-codes t >= threshold as predicting bit 1, so an inverted leak direction (e.g. CLI input --intensity=-10, which is currently accepted) yields near-chance acc_* despite high mutual information. That produces misleading experiment conclusions for valid parameterizations; either reject negative intensity up front or evaluate both comparator polarities and keep the better one.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a deterministic, runnable Experiment 3 (timing-leak simulation) to DiscOS’ sim surface area, making it easy to reproduce results via both library APIs and the CLI, and to persist outputs as artifacts.
Changes:
- Introduces
crates/discos-core/src/experiments/exp3.rswithExp3Config,Exp3Result, andrun_exp3(seeded RNG, threshold attacker, MI estimator). - Exports
exp3from theexperimentsmodule and adds integration/unit/property tests for expected trends and determinism. - Adds a feature-gated CLI entrypoint (
discos sim run exp3) that writes JSON/MD result artifacts, plus commits a default artifact pair underartifacts/.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| crates/discos-core/src/experiments/exp3.rs | Implements the Exp3 simulation runner and statistics (accuracy + MI). |
| crates/discos-core/src/experiments/mod.rs | Exposes exp3 in the experiments module. |
| crates/discos-core/tests/exp3_tests.rs | Adds async unit tests and proptests for ordering, chance behavior, MI monotonicity, and fixed-seed “golden” checks. |
| crates/discos-cli/src/main.rs | Adds discos sim run exp3 command to run the simulation and write JSON/MD outputs. |
| artifacts/exp3/default/exp3_results.json | Adds a committed default JSON output example for Exp3. |
| artifacts/exp3/default/exp3_results.md | Adds a committed default Markdown output example for Exp3. |
Comments suppressed due to low confidence (4)
crates/discos-core/src/experiments/exp3.rs:4
exp3.rsis missing the repository’s standard Apache-2.0 copyright/license header that appears at the top of the other experiment modules (e.g.exp0.rs,exp1.rs,exp2.rs). Please add the same header here for consistency and licensing clarity.
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
crates/discos-core/src/experiments/exp3.rs:45
run_exp3validates thatintensityis finite, but it allows negative values. With the current fixed-direction threshold attacker (pred = 1whent >= threshold), a negative intensity flips the separation and can force accuracy down to ~chance even when the signal is perfectly separable. Consider enforcingintensity >= 0.0(and/or learning the direction during training) so the simulation behaves consistently with the intended “signal intensity” parameter.
anyhow::ensure!(cfg.intensity.is_finite(), "intensity must be finite");
anyhow::ensure!(cfg.noise_sigma.is_finite(), "noise_sigma must be finite");
crates/discos-core/src/experiments/exp3.rs:54
residual_frac_dlc/residual_frac_plnare only checked for finiteness and non-negativity, but as “residual fractions” they likely should be constrained to[0.0, 1.0](and typicallyresidual_frac_pln <= residual_frac_dlc <= 1.0). Allowing values > 1 can make the defended channels leak more than the standard channel, which can break assumptions/tests about ordering and makes CLI inputs easy to misuse.
anyhow::ensure!(
cfg.residual_frac_dlc.is_finite() && cfg.residual_frac_dlc >= 0.0,
"residual_frac_dlc must be finite and non-negative"
);
anyhow::ensure!(
cfg.residual_frac_pln.is_finite() && cfg.residual_frac_pln >= 0.0,
"residual_frac_pln must be finite and non-negative"
);
crates/discos-core/tests/exp3_tests.rs:58
- The fixed-seed “golden value” assertions use a very tight absolute tolerance (
1e-12) on floating-point outputs derived from transcendentals (ln,sqrt,cos,log2). This can be brittle across different libm implementations / architectures and may cause flaky failures. Consider loosening the tolerance (e.g.1e-8/1e-6) or asserting on rounded/serialized values instead of exact f64s.
assert!((result.acc_standard - 1.0).abs() <= 1e-12);
assert!((result.acc_dlc - 0.6136666666666667).abs() <= 1e-12);
assert!((result.acc_pln - 0.5076666666666667).abs() <= 1e-12);
assert!((result.mi_standard_bits - 0.9785881470241701).abs() <= 1e-12);
assert!((result.mi_dlc_bits - 0.05021746994008992).abs() <= 1e-12);
Motivation
Description
crates/discos-core/src/experiments/exp3.rsimplementingExp3ConfigandExp3Resultand the runnerrun_exp3using a seededChaCha20Rng, Gaussian noise sampling, a train/eval single-threshold attacker, and equal-frequency binning mutual information estimator.exp3incrates/discos-core/src/experiments/mod.rsso the experiment is available under thesimfeature.crates/discos-core/tests/exp3_tests.rscovering ordering (acc_standard > acc_dlc > acc_pln), PLN near-chance, MI monotonicity, deterministic golden-values for a fixed seed, and proptest properties (intensity=0and residual-frac bounds).discos sim run exp3incrates/discos-cli/src/main.rswhich accepts experiment parameters and writesexp3_results.jsonandexp3_results.mdto the specified output directory.Testing
cargo fmt --checkandcargo clippy --workspace --all-targets -- -D warningsand they passed.cargo test --workspaceandcargo test -p discos-core --features sim --test exp3_tests, and all Exp3 tests (unit + proptest cases) passed.cargo run -p discos-cli --features sim -- sim run exp3 --out artifacts/exp3/defaultwhich producedartifacts/exp3/default/exp3_results.jsonandexp3_results.mdsuccessfully.Codex Task