"""Aggregate every reduced-round SHA-256 result into results/reduced_round_sha256/summary.json (numbers the paper quotes). PYTHONPATH=src .venv/bin/python experiments/reduced_round_sha256/make_summary.py """ from __future__ import annotations import json, pathlib, statistics, sys, time from common import provenance, ROOT RES = ROOT / "results" / "reduced_round_sha256" def load(name): p = RES / name return json.loads(p.read_text()) if p.exists() else None def main(): t0 = time.time() out = {} # ---- diffusion docs = [json.loads(p.read_text()) for p in sorted(RES.glob("diffusion_seed*.json"))] if docs: diff = {} for cfg in docs[0]["params"]["configs"]: fds = [d["measurements"][cfg]["full_diffusion_step"] for d in docs] ratios = [d["measurements"][cfg]["mean_flip_ratio_by_step"] for d in docs] mean_ratio = [statistics.mean(r[t] for r in ratios) for t in range(64)] diff[cfg] = {"full_diffusion_step_by_seed": fds, "full_diffusion_step": max(fds), "mean_flip_ratio_by_step": [round(x, 4) for x in mean_ratio], "flip_ratio_step64": round(mean_ratio[63], 4), "hamming_mean_step64": round(statistics.mean(d["measurements"][cfg]["hamming_mean_by_step"][63] for d in docs), 2), "hamming_sd_step64": round(statistics.mean(d["measurements"][cfg]["hamming_sd_by_step"][63] for d in docs), 2), "random_oracle_flip_ratio": round(statistics.mean(d["measurements"][cfg]["random_oracle_control"]["flip_ratio_mean"] for d in docs), 4), "random_oracle_flip_sd": round(statistics.mean(d["measurements"][cfg]["random_oracle_control"]["flip_ratio_sd"] for d in docs), 4)} out["diffusion"] = {"n_per_seed": docs[0]["params"]["n"], "seeds": [d["seed"] for d in docs], "threshold": docs[0]["params"]["threshold"], "by_config": diff, "hosts": sorted({d["host"]["hostname"] for d in docs})} # ---- bias docs = [json.loads(p.read_text()) for p in sorted(RES.glob("bias_seed*.json"))] if docs: rs = docs[0]["params"]["r_list"]; by = {} for r in rs: cs = [d["measurements"]["by_r"][str(r)] for d in docs] by[str(r)] = {"max_bit_bias_by_seed": [round(c["max_bit_bias"], 4) for c in cs], "n_bits_bias_over_4sigma_by_seed": [c["n_bits_bias_over_4sigma"] for c in cs], "max_abs_corr_by_seed": [round(c["max_abs_corr"], 4) for c in cs], "n_pairs_corr_over_4sigma_by_seed": [c["n_pairs_corr_over_4sigma"] for c in cs], "chi2_bytes_rejected_by_seed": [c["chi2_n_bytes_rejected_bonferroni"] for c in cs], "chi2_min_p_by_seed": [c["chi2_min_p"] for c in cs]} ro = [d["measurements"]["random_oracle_control"] for d in docs] by["random_oracle"] = {"max_bit_bias_by_seed": [round(c["max_bit_bias"], 4) for c in ro], "n_pairs_corr_over_4sigma_by_seed": [c["n_pairs_corr_over_4sigma"] for c in ro], "chi2_bytes_rejected_by_seed": [c["chi2_n_bytes_rejected_bonferroni"] for c in ro]} first_clean = next((r for r in rs if all(by[str(r)]["n_bits_bias_over_4sigma_by_seed"][i] == 0 and by[str(r)]["chi2_bytes_rejected_by_seed"][i] == 0 for i in range(len(docs)))), None) first_corr_clean = next((r for r in rs if all(x <= 3 for x in by[str(r)]["n_pairs_corr_over_4sigma_by_seed"])), None) out["bias"] = {"n_per_seed": docs[0]["params"]["n"], "seeds": [d["seed"] for d in docs], "r_list": rs, "bias_threshold_4sigma": docs[0]["measurements"]["by_r"]["1"]["bias_threshold_4sigma"], "corr_threshold_4sigma": docs[0]["measurements"]["by_r"]["1"]["corr_threshold_4sigma"], "expected_pairs_under_null": docs[0]["measurements"]["by_r"]["1"]["expected_pairs_under_null"], "first_r_with_no_bit_bias_and_no_chi2_rejection": first_clean, "first_r_with_correlation_count_at_noise_level": first_corr_clean, "by_r": by} # ---- preimage d = load("preimage_sat_scaling.json") if d: S = d["measurements"]["summary"] largest = {} for key, c in S.items(): if c["solved_fraction"] > 0: g = c["solver"] + ("" if c["placement"] == "first" else "_spread") best = largest.get(g) if best is None or (c["r"], c["k"]) > (best["r"], best["k"]): largest[g] = {"r": c["r"], "k": c["k"], "solved_fraction": c["solved_fraction"], "median_wall_s": c["median_wall_s"]} frontier = {} for sol in ("cadical", "kissat", "z3"): for pl in ("first", "spread"): rows = {} for r in d["params"]["r_list"]: ks = [c["k"] for c in S.values() if c["solver"] == sol and c["placement"] == pl and c["r"] == r and c["solved_fraction"] >= 0.5] rows[str(r)] = max(ks) if ks else None if any(v is not None for v in rows.values()): frontier[sol + ("" if pl == "first" else "_spread")] = rows out["preimage_sat"] = {"n_cells": d["n_cells"], "timeout_s": d["params"]["timeout_s"], "hosts": sorted({h for c in S.values() for h in c["hosts"]}), "largest_solved_cell_by_solver": largest, "max_k_solved_majority_by_r": frontier, "all_sat_answers_verified": all(c["all_verified"] in (True, None) for c in S.values()), "cells": S} # ---- collision d = load("collision_sat.json") if d: S = d["measurements"]["summary"] cells = d["measurements"]["cells"] largest = {} for c in S.values(): g = f'{c["solver"]}:iv_{c["iv"]}:ff{int(c["feedforward"])}' if c["solved_fraction"] > 0 and (g not in largest or c["r"] > largest[g]["r"]): largest[g] = {"r": c["r"], "solved_fraction": c["solved_fraction"], "median_wall_s_solved": c["median_wall_s_solved"]} unsat = sorted({(c["cell"]["r"], c["cell"]["iv"], c["cell"]["feedforward"], c["cell"]["solver"]) for c in cells if c["status"] == "unsat"}) examples = {} for c in cells: if c["status"] == "sat" and c.get("verified"): g = f'iv_{c["cell"]["iv"]}:ff{int(c["cell"]["feedforward"])}' if g not in examples or c["cell"]["r"] > examples[g]["r"]: examples[g] = {"r": c["cell"]["r"], "solver": c["cell"]["solver"], "message1_hex": c["message1_hex"], "message2_hex": c["message2_hex"], "iv_hex": c["iv_hex"], "output_hex": c["output_hex"], "differing_words": c["differing_words"]} out["collision_sat"] = {"n_cells": d["n_cells"], "timeout_s": d["params"]["timeout_s"], "hosts": sorted({h for c in S.values() for h in c["hosts"]}), "largest_solved_r_by_variant": largest, "proven_unsat_cells (r, iv, feedforward, solver)": unsat, "all_collisions_verified": all(c["all_verified"] in (True, None) for c in S.values()), "largest_verified_collision_examples": examples, "cells": S} # ---- local collision d = load("local_collision.json") if d: m = d["measurements"] emp = m["empirical"]; sat = m["sat"] out["local_collision"] = { "n_per_bit": d["params"]["n_per_bit"], "seed": d["seed"], "host": d["host"]["hostname"], "linear_model_all_32_single_bit_cancel": all(v["cancels_after_9_steps"] for v in m["linear_model"].values()), "pattern_formula": m["pattern_formula"], "pattern_bit31_hex": m["linear_model"]["31"]["pattern_hex"], "pattern_bit0_hex": m["linear_model"]["0"]["pattern_hex"], "empirical_collisions_total": sum(e["n_collisions"] for e in emp), "empirical_p_collision_by_bit": [e["p_collision"] for e in emp], "rule_of_three_upper_bound": 3 / d["params"]["n_per_bit"], "survival_after_step_i_by_bit": [e["survival_fraction_by_step"][0] for e in emp], "survival_after_step_i+1_by_bit": [e["survival_fraction_by_step"][1] for e in emp], "survival_after_step_i+2_by_bit": [e["survival_fraction_by_step"][2] for e in emp], "sat_timeout_s": d["params"]["sat_timeout_s"], "sat_found_verified_bits": [s["bit"] for s in sat if s.get("verified") is True], "sat_timeout_bits": [s["bit"] for s in sat if s["status"] != "sat"], "sat_wall_s_by_bit": {str(s["bit"]): s["wall_s"] for s in sat}, "sat_conflicts_by_bit": {str(s["bit"]): s.get("conflicts") for s in sat}, } d2 = load("local_collision_bits31_0_seed2.json") if d2: out["local_collision"]["second_run_bits31_0"] = {"seed": d2["seed"], "sat": [{k: s.get(k) for k in ("bit", "status", "wall_s", "conflicts", "verified")} for s in d2["measurements"]["sat"]], "empirical_collisions_total": sum(e["n_collisions"] for e in d2["measurements"]["empirical"])} provenance.record("sha256_summary", {"sources": sorted(p.name for p in RES.glob("*.json") if p.name != "summary.json")}, out, out=RES / "summary.json", started=t0) print(json.dumps({k: {kk: vv for kk, vv in v.items() if kk not in ("cells", "by_r", "by_config")} for k, v in out.items()}, indent=1, default=str)[:6000]) if __name__ == "__main__": main()