use logicaffeine_proof::cyclotomic::{
approximation_scale, cyclotomic_units, recover_short_generator, recovery_margin, Cyclo,
};
use logicaffeine_proof::factor::{mod_inverse, modpow};
use logicaffeine_proof::fp2::{
derive_isogeny_path2, fp2_const, full_order_basis2, kernel_generator2, keyspace_codomain_classes,
push_through2, recover_secret2, Curve2,
};
use logicaffeine_proof::hyperelliptic::{
cantor_add, count_curve_fp, genus2_jacobian_order, genus2_jacobian_order_general, glue_shared_2torsion,
jac_identity, jac_scalar_mul, poly_eval, poly_mul, richelot, Mumford,
};
use logicaffeine_base::BigInt;
fn bi(x: i64) -> BigInt {
BigInt::from_i64(x)
}
#[test]
fn reach_win_cdpr_recovers_the_short_generator() {
let n = 8;
let secret = Cyclo::from_ints(n, &[1, -1, 0, 0, 0, 0, 0, 0]); let units = cyclotomic_units(n);
let mask = units[0].mul(&units[1]); let public = secret.mul(&mask); assert!(public.coeff_norm() > secret.coeff_norm());
let recovered = recover_short_generator(&public).expect("CDPR recovery");
assert_eq!(recovered.coeff_norm(), secret.coeff_norm(), "recovered a generator as short as the secret");
assert!(!recovered.is_unit(), "it generates the secret ideal, not R");
}
#[test]
fn reach_win_images_to_generator_and_keyspace_collapse() {
let p = BigInt::parse_decimal("107").unwrap();
let e0 = Curve2::new(fp2_const(1, &p), fp2_const(0, &p), p.clone());
let (pa, qa) = full_order_basis2(&e0, 3, 3).expect("rank-2 E[3³]");
let (pb, qb) = full_order_basis2(&e0, 2, 2).expect("rank-2 E[2²]");
let gen = kernel_generator2(&e0, &pa, &qa, &bi(7));
let path = derive_isogeny_path2(&e0, &gen, 3, 3).unwrap();
let images = (push_through2(&path, 3, &pb).unwrap(), push_through2(&path, 3, &qb).unwrap());
let (_s, _g, rpath) =
recover_secret2(&e0, (&pa, &qa), 3, 3, (&pb, &qb), (&images.0, &images.1)).expect("recovery");
assert_eq!(push_through2(&rpath, 3, &pb).unwrap(), images.0, "recovered isogeny reproduces the images");
let classes = keyspace_codomain_classes(&e0, (&pa, &qa), 3, 3);
let total: usize = classes.iter().map(|(_, s)| s.len()).sum();
assert_eq!(total, 27, "the whole keyspace is partitioned");
assert!(classes.len() < 27, "and it COLLAPSES into Aut-orbits (symmetry = compression)");
}
#[test]
fn reach_mechanism_gluing_jacobian_and_richelot_dual() {
let p = BigInt::parse_decimal("103").unwrap();
let g = glue_shared_2torsion(&[bi(3), bi(7), bi(20)], &p);
let e1 = count_curve_fp(&g.e1, &p, 2) as i128;
let e2 = count_curve_fp(&g.e2, &p, 2) as i128;
assert_eq!(genus2_jacobian_order(&g.sextic, &p), e1 * e2, "matched-pair gluing verified");
let r = richelot(&[[bi(1), bi(0), bi(1)], [bi(2), bi(1), bi(1)], [bi(5), bi(3), bi(1)]], &p);
let dinv = mod_inverse(&r.delta, &p).unwrap();
let reduce = |c: &BigInt| {
let m = c.mul(&dinv);
let rr = m.div_rem(&p).map(|(_, r)| r).unwrap_or(m);
if rr.is_negative() {
rr.add(&p)
} else {
rr
}
};
let cprime: Vec<BigInt> = r.codomain.iter().map(reduce).collect();
assert_eq!(
genus2_jacobian_order_general(&r.domain, &p),
genus2_jacobian_order_general(&cprime, &p),
"Richelot dual is genuinely isogenous"
);
let mut f = vec![bi(1)];
for root in [0i64, 1, 2, 3, 4] {
f = poly_mul(&f, &[p.sub(&bi(root)), bi(1)], &p); }
let jac = genus2_jacobian_order_general(&f, &p) as u128;
let sqrt_exp = p.add(&bi(1)).div_rem(&bi(4)).map(|(q, _)| q).unwrap(); let d = (0..103i64)
.find_map(|x0| {
let fx = poly_eval(&f, &bi(x0), &p);
let y = modpow(&fx, &sqrt_exp, &p);
(modpow(&y, &bi(2), &p) == fx && !y.is_zero())
.then(|| Mumford { u: vec![p.sub(&bi(x0)), bi(1)], v: vec![y] })
})
.expect("a rational point");
assert_eq!(jac_scalar_mul(jac, &d, &f, &p), jac_identity(), "#Jac · D = 0 — Cantor is a genuine group");
}
#[test]
fn reach_wall_mlkem_is_upstream_of_the_collapse() {
let (s8, s64) = (approximation_scale(8), approximation_scale(64));
assert!(s64 > s8 && s8 > 0.0, "the approximation scale grows with n: {s8} → {s64}");
let short = Cyclo::from_ints(8, &[1, -1, 0, 0, 0, 0, 0, 0]);
assert!(recovery_margin(&short) < 1.0, "short generators are inside the wall — the rung is cheap");
}