Download src/lib.rs from Jessedbrown/path2-two-shadow-recovery: direct link, hf CLI and curl.
- Browser
- Download file 48.6 kB
-
https://huggingface.co/Jessedbrown/path2-two-shadow-recovery/resolve/main/src/lib.rs
- Command line
-
hf download hf://Jessedbrown/path2-two-shadow-recovery/src/lib.rs
-
curl -L -o lib.rs https://huggingface.co/Jessedbrown/path2-two-shadow-recovery/resolve/main/src/lib.rs
48.6 kB
| //! # path2-two-shadow-recovery — Path 2 of the shadow-resolution capstone | |
| //! | |
| //! Pure Rust, ZERO deps. The complement to Path 1 (content-addressed RECALL of a *retained* | |
| //! object): here **nothing is retained.** An object is recovered from **two jointly-injective | |
| //! lossy shadows** — each shadow alone is provably ambiguous (non-injective), the two together | |
| //! over-determine the object and reconstruct it EXACTLY. This is the honest "double binary black | |
| //! hole": two poles cut the fiber `P1^-1(s1) ∩ P2^-1(s2)` to a singleton. | |
| //! | |
| //! Mechanism: CRT over coprime cylinders (the Asolaria CRT-coprime-cylinder lane). For a block `x < R`: | |
| //! shadow1 = x mod p1, shadow2 = x mod p2 (p1,p2 coprime). | |
| //! If `p1*p2 >= R` the pair uniquely determines `x` (CRT) — exact recovery, NO STORE. | |
| //! If `p1*p2 < R` the two shadows don't jointly carry `log2(R)` bits -> HELD (the Shannon | |
| //! boundary; no bijection beats it: E[bits] >= H(X)). | |
| //! | |
| //! Honest ledger: each residue is ~`log2(p)` bits; two shadows total `~log2(p1)+log2(p2)` bits, | |
| //! which is `>= log2(R) = H(x)` for a uniform block — the excess is the over-determination margin | |
| //! that buys "no store". Path 1 pays store(H(X))+tiny-address; Path 2 pays bigger-shadows/no-store. | |
| //! Both honor Shannon. Federation form: party A holds only shadow1, party B only shadow2; neither | |
| //! alone can reconstruct x — recovery is the consent of two independent poles. | |
| // ------------------------------------------------------------ modular arithmetic | |
| fn egcd(a: i128, b: i128) -> (i128, i128, i128) { | |
| if a == 0 { | |
| (b, 0, 1) | |
| } else { | |
| let (g, x, y) = egcd(b % a, a); | |
| (g, y - (b / a) * x, x) | |
| } | |
| } | |
| /// Modular inverse of `a` mod `m` (m need not be prime; returns None if not invertible). | |
| pub fn mod_inv(a: u64, m: u64) -> Option<u64> { | |
| if m == 0 { | |
| return None; | |
| } | |
| let (g, x, _) = egcd((a % m) as i128, m as i128); | |
| if g != 1 { | |
| return None; | |
| } | |
| Some((((x % m as i128) + m as i128) % m as i128) as u64) | |
| } | |
| // ------------------------------------------------------------ one lossy shadow | |
| /// A single lossy shadow of `x`: its residue mod `prime`. Provably non-injective: any | |
| /// `x' = x + k*prime` casts the SAME shadow, so one shadow alone cannot recover `x`. | |
| pub fn shadow(x: u128, prime: u64) -> u64 { | |
| (x % prime as u128) as u64 | |
| } | |
| // ------------------------------------------------------------ two-shadow recovery | |
| pub enum Held { | |
| /// The shadows do not jointly carry log2(range) bits (Shannon boundary). | |
| InsufficientJointCapacity, | |
| /// The moduli are not coprime, so CRT has no unique solution. | |
| NonCoprimeModuli, | |
| /// A requested multi-cylinder subset was empty, out of range, or duplicated. | |
| InvalidCylinderSelection, | |
| /// Multi-cylinder shadow lanes have inconsistent block counts. | |
| MismatchedShadowCount, | |
| /// A selected cylinder residue disagrees with the recovered block. | |
| InconsistentResidue, | |
| /// A pixels-first world slice has impossible dimensions or length. | |
| InvalidSliceGeometry, | |
| /// A pixels-first world slice byte frame is malformed. | |
| InvalidSliceEncoding, | |
| /// A watched black/white round-trip did not reconstruct the same slice. | |
| WatcherDisagreement, | |
| } | |
| /// CRT over two coprime moduli: the unique `x` in `[0, p1*p2)` with `x ≡ s1 (p1)`, `x ≡ s2 (p2)`. | |
| pub fn crt2(s1: u64, p1: u64, s2: u64, p2: u64) -> Result<u128, Held> { | |
| let inv = mod_inv(p1 % p2, p2).ok_or(Held::NonCoprimeModuli)?; // p1^-1 mod p2 | |
| let diff = (((s2 as i128 - s1 as i128) % p2 as i128) + p2 as i128) % p2 as i128; | |
| let t = (diff as u128 * inv as u128) % p2 as u128; | |
| Ok(s1 as u128 + p1 as u128 * t) // in [0, p1*p2) | |
| } | |
| /// Recover `x < range` from its two lossy shadows, WITHOUT a store. `Held` iff the two shadows | |
| /// don't jointly over-determine `x` (p1*p2 < range) — the honest Shannon wall. | |
| pub fn two_shadow_recover(s1: u64, p1: u64, s2: u64, p2: u64, range: u128) -> Result<u128, Held> { | |
| if (p1 as u128) * (p2 as u128) < range { | |
| return Err(Held::InsufficientJointCapacity); | |
| } | |
| crt2(s1, p1, s2, p2) | |
| } | |
| // ------------------------------------------------------------ bytes generalization | |
| /// A two-shadow codec over coprime cylinders for arbitrary byte objects. `block_bytes`-sized | |
| /// blocks are each shadowed by residues mod `p1` and `p2`; recovery is per-block CRT. | |
| /// Invariant checked at construction: `p1*p2 >= 2^(8*block_bytes)` (else recovery would be lossy). | |
| pub struct TwoShadow { | |
| pub p1: u64, | |
| pub p2: u64, | |
| pub block_bytes: usize, | |
| } | |
| /// The two lossy shadows of an object, plus its length (to strip the final pad). Neither | |
| /// `shadow_a` nor `shadow_b` alone can reconstruct the object. | |
| pub struct Shadows { | |
| pub shadow_a: Vec<u64>, // party-A pole: residues mod p1 | |
| pub shadow_b: Vec<u64>, // party-B pole: residues mod p2 | |
| pub orig_len: usize, | |
| } | |
| impl TwoShadow { | |
| /// Default coprime cylinders (~2^25 each; product ~2^50 > 2^48 for 6-byte blocks). | |
| pub const P1: u64 = 33_554_467; // prime just above 2^25 | |
| pub const P2: u64 = 33_554_393; // prime just below 2^25 (coprime to P1) | |
| pub fn new() -> Self { | |
| TwoShadow { | |
| p1: Self::P1, | |
| p2: Self::P2, | |
| block_bytes: 6, | |
| } | |
| } | |
| fn block_range(&self) -> u128 { | |
| 1u128 << (8 * self.block_bytes as u32) | |
| } | |
| /// True iff the two cylinders jointly cover a block (recovery will be exact). | |
| pub fn sufficient(&self) -> bool { | |
| (self.p1 as u128) * (self.p2 as u128) >= self.block_range() | |
| } | |
| fn blocks(&self, data: &[u8]) -> Vec<u128> { | |
| let bb = self.block_bytes; | |
| let mut out = Vec::new(); | |
| for chunk in data.chunks(bb) { | |
| let mut v: u128 = 0; | |
| for &b in chunk { | |
| v = (v << 8) | b as u128; | |
| } | |
| // left-justify short final chunk so the value stays < block_range and round-trips via orig_len | |
| if chunk.len() < bb { | |
| v <<= 8 * (bb - chunk.len()) as u32; | |
| } | |
| out.push(v); | |
| } | |
| out | |
| } | |
| /// Project an object into its TWO lossy shadows (no store; the object is not retained). | |
| pub fn project(&self, data: &[u8]) -> Shadows { | |
| let blocks = self.blocks(data); | |
| Shadows { | |
| shadow_a: blocks.iter().map(|&b| shadow(b, self.p1)).collect(), | |
| shadow_b: blocks.iter().map(|&b| shadow(b, self.p2)).collect(), | |
| orig_len: data.len(), | |
| } | |
| } | |
| /// Recover the EXACT object from its two shadows, WITHOUT a store. `Held` if the cylinders | |
| /// are insufficient (Shannon) or the shadows don't align. | |
| pub fn recover(&self, sh: &Shadows) -> Result<Vec<u8>, Held> { | |
| if !self.sufficient() { | |
| return Err(Held::InsufficientJointCapacity); | |
| } | |
| if sh.shadow_a.len() != sh.shadow_b.len() { | |
| return Err(Held::NonCoprimeModuli); | |
| } | |
| let bb = self.block_bytes; | |
| let range = self.block_range(); | |
| let mut out = Vec::with_capacity(sh.shadow_a.len() * bb); | |
| for (&a, &b) in sh.shadow_a.iter().zip(sh.shadow_b.iter()) { | |
| let x = two_shadow_recover(a, self.p1, b, self.p2, range)?; | |
| // big-endian bytes of the bb-byte block | |
| for i in (0..bb).rev() { | |
| out.push(((x >> (8 * i as u32)) & 0xFF) as u8); | |
| } | |
| } | |
| out.truncate(sh.orig_len); | |
| Ok(out) | |
| } | |
| } | |
| impl Default for TwoShadow { | |
| fn default() -> Self { | |
| Self::new() | |
| } | |
| } | |
| // ------------------------------------------------------------ multi-cylinder / 60D+ Q-PRISM slice lane | |
| /// Default coprime cylinders for the 60D+ slice harness. They are near 2^25 each; | |
| /// any two carry about 50 bits, any three carry about 75 bits. That makes the | |
| /// calculable slice roof explicit: add cylinders, raise the recoverable range. | |
| pub const DEFAULT_60D_CYLINDERS: [u64; 7] = [ | |
| TwoShadow::P1, | |
| TwoShadow::P2, | |
| 33_554_321, | |
| 33_554_287, | |
| 33_554_257, | |
| 33_554_243, | |
| 33_554_173, | |
| ]; | |
| fn gcd_u128(mut a: u128, mut b: u128) -> u128 { | |
| while b != 0 { | |
| let r = a % b; | |
| a = b; | |
| b = r; | |
| } | |
| a | |
| } | |
| fn block_range_for(block_bytes: usize) -> Option<u128> { | |
| if block_bytes >= 16 { | |
| return None; | |
| } | |
| Some(1u128 << (8 * block_bytes as u32)) | |
| } | |
| fn validate_coprime_moduli(moduli: &[u64]) -> Result<(), Held> { | |
| if moduli.is_empty() { | |
| return Err(Held::InvalidCylinderSelection); | |
| } | |
| for (i, &p) in moduli.iter().enumerate() { | |
| if p < 2 { | |
| return Err(Held::NonCoprimeModuli); | |
| } | |
| for &q in &moduli[..i] { | |
| if gcd_u128(p as u128, q as u128) != 1 { | |
| return Err(Held::NonCoprimeModuli); | |
| } | |
| } | |
| } | |
| Ok(()) | |
| } | |
| /// Product of coprime cylinders, or Held if they cannot form a CRT basis. | |
| /// | |
| /// This exact product is intentionally u128-bounded. Use joint_modulus_capped for proof lanes | |
| /// that only need to know whether the product reaches a block range. | |
| pub fn joint_modulus(moduli: &[u64]) -> Result<u128, Held> { | |
| validate_coprime_moduli(moduli)?; | |
| let mut product = 1u128; | |
| for &p in moduli { | |
| product = product | |
| .checked_mul(p as u128) | |
| .ok_or(Held::InsufficientJointCapacity)?; | |
| } | |
| Ok(product) | |
| } | |
| /// Product capped at cap. This prevents high-N cylinder receipts from false-Holding on u128 | |
| /// overflow when the only needed fact is that the product already covers the slice roof. | |
| pub fn joint_modulus_capped(moduli: &[u64], cap: u128) -> Result<u128, Held> { | |
| validate_coprime_moduli(moduli)?; | |
| if cap <= 1 { | |
| return Ok(cap); | |
| } | |
| let mut product = 1u128; | |
| for &p in moduli { | |
| let p = p as u128; | |
| if product >= cap || product > (cap - 1) / p { | |
| return Ok(cap); | |
| } | |
| product *= p; | |
| } | |
| Ok(product) | |
| } | |
| /// Conservative integer floor(log2(product(moduli))). For overflow-sized N, this returns a safe | |
| /// lower bound by summing per-cylinder floors, so receipts never collapse large capacity to zero. | |
| pub fn joint_capacity_bits_floor(moduli: &[u64]) -> Result<u32, Held> { | |
| validate_coprime_moduli(moduli)?; | |
| match joint_modulus(moduli) { | |
| Ok(m) => Ok(127 - m.leading_zeros()), | |
| Err(Held::InsufficientJointCapacity) => { | |
| Ok(moduli.iter().map(|&m| 63 - m.leading_zeros()).sum()) | |
| } | |
| Err(e) => Err(e), | |
| } | |
| } | |
| /// Integer ceil(log2(n)) for selector-bit accounting. `n=1` needs zero selector bits. | |
| pub fn ceil_log2_u128(n: u128) -> u32 { | |
| if n <= 1 { | |
| 0 | |
| } else { | |
| 128 - (n - 1).leading_zeros() | |
| } | |
| } | |
| fn ceil_div_u128(a: u128, b: u128) -> Result<u128, Held> { | |
| if b == 0 { | |
| return Err(Held::InvalidCylinderSelection); | |
| } | |
| Ok(a / b + u128::from(a % b != 0)) | |
| } | |
| /// Number of candidates left after the selected cylinder product constrains a block range. | |
| /// This is the precise "fiber size" that the N-Q-prism has not collapsed yet. | |
| pub fn residual_candidate_count_for(block_bytes: usize, moduli: &[u64]) -> Result<u128, Held> { | |
| let range = block_range_for(block_bytes).ok_or(Held::InsufficientJointCapacity)?; | |
| let modulus = joint_modulus_capped(moduli, range)?; | |
| ceil_div_u128(range, modulus) | |
| } | |
| /// Bits still needed to select one candidate after the shared atlas/cylinders have constrained it. | |
| /// This is where a transfer can honestly fall to 1 or 2 bits: not because entropy vanished, but | |
| /// because the Brown-Hilbert/PID/coprime-cylinder context already paid most of the information. | |
| pub fn residual_selector_bits_for(block_bytes: usize, moduli: &[u64]) -> Result<u32, Held> { | |
| Ok(ceil_log2_u128(residual_candidate_count_for( | |
| block_bytes, | |
| moduli, | |
| )?)) | |
| } | |
| /// Signed capacity margin against the block. Negative means underdetermined; zero means exact-ish; | |
| /// positive means overdetermined redundancy. This is the safe form of the "negative bits" intuition: | |
| /// the residual can go below zero only as a margin metric, never as literal sub-Shannon payload. | |
| pub fn signed_capacity_margin_bits_floor(block_bytes: usize, moduli: &[u64]) -> Result<i32, Held> { | |
| let block_bits = (8 * block_bytes) as i32; | |
| Ok(joint_capacity_bits_floor(moduli)? as i32 - block_bits) | |
| } | |
| /// CRT over N pairwise-coprime cylinders. This is the multi-cylinder Path-2 join: | |
| /// every residue is lossy alone; any subset whose joint product covers the block | |
| /// range recovers exactly. | |
| pub fn crt_many(residues: &[(u64, u64)]) -> Result<u128, Held> { | |
| if residues.is_empty() { | |
| return Err(Held::InvalidCylinderSelection); | |
| } | |
| let mut x = 0u128; | |
| let mut modulus = 1u128; | |
| for &(residue, prime) in residues { | |
| if gcd_u128(modulus, prime as u128) != 1 { | |
| return Err(Held::NonCoprimeModuli); | |
| } | |
| let current = (x % prime as u128) as u64; | |
| let diff = | |
| (((residue as i128 - current as i128) % prime as i128) + prime as i128) % prime as i128; | |
| let inv = mod_inv((modulus % prime as u128) as u64, prime).ok_or(Held::NonCoprimeModuli)?; | |
| let t = (diff as u128 * inv as u128) % prime as u128; | |
| x += modulus * t; | |
| modulus = modulus | |
| .checked_mul(prime as u128) | |
| .ok_or(Held::InsufficientJointCapacity)?; | |
| } | |
| Ok(x) | |
| } | |
| pub struct MultiCylinder { | |
| pub primes: Vec<u64>, | |
| pub block_bytes: usize, | |
| } | |
| pub struct MultiShadows { | |
| /// residues[cylinder][block] | |
| pub residues: Vec<Vec<u64>>, | |
| pub orig_len: usize, | |
| pub block_bytes: usize, | |
| } | |
| impl MultiCylinder { | |
| pub fn default_60d() -> Self { | |
| Self { | |
| primes: DEFAULT_60D_CYLINDERS.to_vec(), | |
| block_bytes: 8, | |
| } | |
| } | |
| pub fn block_range(&self) -> Option<u128> { | |
| block_range_for(self.block_bytes) | |
| } | |
| pub fn joint_capacity_bits_floor(&self, indices: &[usize]) -> Result<u32, Held> { | |
| let primes = self.selected_primes(indices)?; | |
| joint_capacity_bits_floor(&primes) | |
| } | |
| pub fn residual_selector_bits(&self, indices: &[usize]) -> Result<u32, Held> { | |
| let primes = self.selected_primes(indices)?; | |
| residual_selector_bits_for(self.block_bytes, &primes) | |
| } | |
| pub fn signed_capacity_margin_bits_floor(&self, indices: &[usize]) -> Result<i32, Held> { | |
| let primes = self.selected_primes(indices)?; | |
| signed_capacity_margin_bits_floor(self.block_bytes, &primes) | |
| } | |
| pub fn sufficient_subset(&self, indices: &[usize]) -> Result<bool, Held> { | |
| let moduli = self.selected_primes(indices)?; | |
| let range = self.block_range().ok_or(Held::InsufficientJointCapacity)?; | |
| Ok(joint_modulus_capped(&moduli, range)? >= range) | |
| } | |
| pub fn select_for_residual_bits(&self, target_bits: u32) -> Result<Vec<usize>, Held> { | |
| let mut selected = Vec::new(); | |
| for idx in 0..self.primes.len() { | |
| selected.push(idx); | |
| if self.residual_selector_bits(&selected)? <= target_bits { | |
| return Ok(selected); | |
| } | |
| } | |
| Err(Held::InsufficientJointCapacity) | |
| } | |
| fn sufficient_prefix(&self, indices: &[usize]) -> Result<Vec<usize>, Held> { | |
| let mut prefix = Vec::new(); | |
| for &idx in indices { | |
| prefix.push(idx); | |
| if self.sufficient_subset(&prefix)? { | |
| return Ok(prefix); | |
| } | |
| } | |
| Err(Held::InsufficientJointCapacity) | |
| } | |
| fn selected_primes(&self, indices: &[usize]) -> Result<Vec<u64>, Held> { | |
| if indices.is_empty() { | |
| return Err(Held::InvalidCylinderSelection); | |
| } | |
| let mut seen = Vec::new(); | |
| let mut out = Vec::new(); | |
| for &idx in indices { | |
| if idx >= self.primes.len() || seen.contains(&idx) { | |
| return Err(Held::InvalidCylinderSelection); | |
| } | |
| seen.push(idx); | |
| out.push(self.primes[idx]); | |
| } | |
| Ok(out) | |
| } | |
| fn blocks(&self, data: &[u8]) -> Vec<u128> { | |
| let bb = self.block_bytes; | |
| let mut out = Vec::new(); | |
| for chunk in data.chunks(bb) { | |
| let mut v = 0u128; | |
| for &b in chunk { | |
| v = (v << 8) | b as u128; | |
| } | |
| if chunk.len() < bb { | |
| v <<= 8 * (bb - chunk.len()) as u32; | |
| } | |
| out.push(v); | |
| } | |
| out | |
| } | |
| pub fn project(&self, data: &[u8]) -> MultiShadows { | |
| let blocks = self.blocks(data); | |
| let residues = self | |
| .primes | |
| .iter() | |
| .map(|&p| blocks.iter().map(|&b| shadow(b, p)).collect()) | |
| .collect(); | |
| MultiShadows { | |
| residues, | |
| orig_len: data.len(), | |
| block_bytes: self.block_bytes, | |
| } | |
| } | |
| pub fn recover_from(&self, shadows: &MultiShadows, indices: &[usize]) -> Result<Vec<u8>, Held> { | |
| if shadows.residues.len() != self.primes.len() || shadows.block_bytes != self.block_bytes { | |
| return Err(Held::MismatchedShadowCount); | |
| } | |
| let selected = self.selected_primes(indices)?; | |
| let basis_indices = self.sufficient_prefix(indices)?; | |
| let block_count = shadows.residues.first().map(|r| r.len()).unwrap_or(0); | |
| if shadows.residues.iter().any(|r| r.len() != block_count) { | |
| return Err(Held::MismatchedShadowCount); | |
| } | |
| let bb = self.block_bytes; | |
| let mut out = Vec::with_capacity(block_count * bb); | |
| for block in 0..block_count { | |
| let mut basis = Vec::with_capacity(basis_indices.len()); | |
| for &idx in &basis_indices { | |
| basis.push((shadows.residues[idx][block], self.primes[idx])); | |
| } | |
| let x = crt_many(&basis)?; | |
| for (&idx, &modulus) in indices.iter().zip(selected.iter()) { | |
| if shadow(x, modulus) != shadows.residues[idx][block] { | |
| return Err(Held::InconsistentResidue); | |
| } | |
| } | |
| for i in (0..bb).rev() { | |
| out.push(((x >> (8 * i as u32)) & 0xFF) as u8); | |
| } | |
| } | |
| out.truncate(shadows.orig_len); | |
| Ok(out) | |
| } | |
| } | |
| // ------------------------------------------------------------ BEHCS wavelengths + Host8/SHA lane | |
| pub enum BehcsRung { | |
| Behcs64, | |
| Behcs256, | |
| Behcs1024, | |
| } | |
| impl BehcsRung { | |
| pub fn bits(self) -> u8 { | |
| match self { | |
| BehcsRung::Behcs64 => 6, | |
| BehcsRung::Behcs256 => 8, | |
| BehcsRung::Behcs1024 => 10, | |
| } | |
| } | |
| pub fn label(self) -> &'static str { | |
| match self { | |
| BehcsRung::Behcs64 => "BEHCS-64", | |
| BehcsRung::Behcs256 => "BEHCS-256", | |
| BehcsRung::Behcs1024 => "BEHCS-1024", | |
| } | |
| } | |
| } | |
| pub struct BehcsFrame { | |
| pub rung: BehcsRung, | |
| pub nbytes: usize, | |
| pub symbols: Vec<u16>, | |
| } | |
| impl BehcsFrame { | |
| pub fn encode(rung: BehcsRung, bytes: &[u8]) -> Self { | |
| Self { | |
| rung, | |
| nbytes: bytes.len(), | |
| symbols: pack_symbols(bytes, rung.bits()), | |
| } | |
| } | |
| pub fn decode(&self) -> Vec<u8> { | |
| unpack_symbols(&self.symbols, self.rung.bits(), self.nbytes) | |
| } | |
| } | |
| fn pack_symbols(bytes: &[u8], nbits: u8) -> Vec<u16> { | |
| let mut bits = 0u32; | |
| let mut held = 0u8; | |
| let mask = (1u32 << nbits) - 1; | |
| let mut out = Vec::new(); | |
| for &b in bytes { | |
| bits = (bits << 8) | b as u32; | |
| held += 8; | |
| while held >= nbits { | |
| held -= nbits; | |
| out.push(((bits >> held) & mask) as u16); | |
| } | |
| bits &= if held == 0 { 0 } else { (1u32 << held) - 1 }; | |
| } | |
| if held > 0 { | |
| out.push(((bits << (nbits - held)) & mask) as u16); | |
| } | |
| out | |
| } | |
| fn unpack_symbols(symbols: &[u16], nbits: u8, nbytes: usize) -> Vec<u8> { | |
| let mut bits = 0u32; | |
| let mut held = 0u8; | |
| let mut out = Vec::with_capacity(nbytes); | |
| let mask = (1u32 << nbits) - 1; | |
| for &s in symbols { | |
| bits = (bits << nbits) | (s as u32 & mask); | |
| held += nbits; | |
| while held >= 8 { | |
| held -= 8; | |
| out.push(((bits >> held) & 0xff) as u8); | |
| } | |
| bits &= if held == 0 { 0 } else { (1u32 << held) - 1 }; | |
| } | |
| out.truncate(nbytes); | |
| out | |
| } | |
| pub struct Sha256Digest(pub [u8; 32]); | |
| impl Sha256Digest { | |
| pub fn hex(self) -> String { | |
| hex_lower(&self.0) | |
| } | |
| pub fn sha16_hex(self) -> String { | |
| hex_lower(&self.0[..8]) | |
| } | |
| pub fn host8(self) -> [u8; 8] { | |
| let mut out = [0u8; 8]; | |
| out.copy_from_slice(&self.0[..8]); | |
| out | |
| } | |
| } | |
| pub fn hex_lower(bytes: &[u8]) -> String { | |
| const HEX: &[u8; 16] = b"0123456789abcdef"; | |
| let mut s = String::with_capacity(bytes.len() * 2); | |
| for &b in bytes { | |
| s.push(HEX[(b >> 4) as usize] as char); | |
| s.push(HEX[(b & 0x0f) as usize] as char); | |
| } | |
| s | |
| } | |
| pub fn sha256(data: &[u8]) -> Sha256Digest { | |
| const H0: [u32; 8] = [ | |
| 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, | |
| 0x5be0cd19, | |
| ]; | |
| const K: [u32; 64] = [ | |
| 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, | |
| 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, | |
| 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, | |
| 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, | |
| 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, | |
| 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, | |
| 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, | |
| 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
| 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, | |
| 0xc67178f2, | |
| ]; | |
| let mut h = H0; | |
| let bit_len = (data.len() as u64) * 8; | |
| let mut msg = data.to_vec(); | |
| msg.push(0x80); | |
| while (msg.len() % 64) != 56 { | |
| msg.push(0); | |
| } | |
| msg.extend_from_slice(&bit_len.to_be_bytes()); | |
| for chunk in msg.chunks(64) { | |
| let mut w = [0u32; 64]; | |
| for i in 0..16 { | |
| w[i] = u32::from_be_bytes([ | |
| chunk[i * 4], | |
| chunk[i * 4 + 1], | |
| chunk[i * 4 + 2], | |
| chunk[i * 4 + 3], | |
| ]); | |
| } | |
| for i in 16..64 { | |
| let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3); | |
| let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10); | |
| w[i] = w[i - 16] | |
| .wrapping_add(s0) | |
| .wrapping_add(w[i - 7]) | |
| .wrapping_add(s1); | |
| } | |
| let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh) = | |
| (h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]); | |
| for i in 0..64 { | |
| let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25); | |
| let ch = (e & f) ^ ((!e) & g); | |
| let temp1 = hh | |
| .wrapping_add(s1) | |
| .wrapping_add(ch) | |
| .wrapping_add(K[i]) | |
| .wrapping_add(w[i]); | |
| let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22); | |
| let maj = (a & b) ^ (a & c) ^ (b & c); | |
| let temp2 = s0.wrapping_add(maj); | |
| hh = g; | |
| g = f; | |
| f = e; | |
| e = d.wrapping_add(temp1); | |
| d = c; | |
| c = b; | |
| b = a; | |
| a = temp1.wrapping_add(temp2); | |
| } | |
| h[0] = h[0].wrapping_add(a); | |
| h[1] = h[1].wrapping_add(b); | |
| h[2] = h[2].wrapping_add(c); | |
| h[3] = h[3].wrapping_add(d); | |
| h[4] = h[4].wrapping_add(e); | |
| h[5] = h[5].wrapping_add(f); | |
| h[6] = h[6].wrapping_add(g); | |
| h[7] = h[7].wrapping_add(hh); | |
| } | |
| let mut out = [0u8; 32]; | |
| for (i, word) in h.iter().enumerate() { | |
| out[i * 4..i * 4 + 4].copy_from_slice(&word.to_be_bytes()); | |
| } | |
| Sha256Digest(out) | |
| } | |
| pub struct HyperCoord60 { | |
| pub axes: [u16; 60], | |
| } | |
| impl HyperCoord60 { | |
| pub fn from_digest(digest: Sha256Digest) -> Self { | |
| let mut axes = [0u16; 60]; | |
| for (i, axis) in axes.iter_mut().enumerate() { | |
| let a = digest.0[(i * 7) % 32] as u16; | |
| let b = digest.0[(i * 7 + 1) % 32] as u16; | |
| *axis = ((a << 8) | b) % 1024; | |
| } | |
| Self { axes } | |
| } | |
| pub fn xyz(&self) -> (u16, u16, u16) { | |
| (self.axes[0], self.axes[1], self.axes[2]) | |
| } | |
| pub fn prefix6(&self) -> String { | |
| let mut s = String::new(); | |
| for i in 0..6 { | |
| if i > 0 { | |
| s.push('.'); | |
| } | |
| s.push_str(&self.axes[i].to_string()); | |
| } | |
| s | |
| } | |
| } | |
| pub struct QPrismSlice3d { | |
| pub sha256: Sha256Digest, | |
| pub host8_hex: String, | |
| pub coord: HyperCoord60, | |
| pub shadows: MultiShadows, | |
| pub behcs64: BehcsFrame, | |
| pub behcs256: BehcsFrame, | |
| pub behcs1024: BehcsFrame, | |
| } | |
| impl QPrismSlice3d { | |
| pub fn project(data: &[u8], codec: &MultiCylinder) -> Self { | |
| let digest = sha256(data); | |
| Self { | |
| sha256: digest, | |
| host8_hex: hex_lower(&digest.host8()), | |
| coord: HyperCoord60::from_digest(digest), | |
| shadows: codec.project(data), | |
| behcs64: BehcsFrame::encode(BehcsRung::Behcs64, data), | |
| behcs256: BehcsFrame::encode(BehcsRung::Behcs256, data), | |
| behcs1024: BehcsFrame::encode(BehcsRung::Behcs1024, data), | |
| } | |
| } | |
| pub fn hbp_rows(&self, codec: &MultiCylinder, slice_id: &str) -> Vec<String> { | |
| let (x, y, z) = self.coord.xyz(); | |
| let mut rows = Vec::new(); | |
| rows.push(format!("Q3DSLICE|id={}|host8={}|sha256={}|sha16={}|dims=60|x={}|y={}|z={}|bh_prefix={}|block_bytes={}|cylinders={}|body_in_row=0|json=0", slice_id, self.host8_hex, self.sha256.hex(), self.sha256.sha16_hex(), x, y, z, self.coord.prefix6(), codec.block_bytes, codec.primes.len())); | |
| for frame in [&self.behcs64, &self.behcs256, &self.behcs1024] { | |
| rows.push(format!( | |
| "Q3DWAVE|id={}|rung={}|symbols={}|nbytes={}|sha16={}|roundtrip=1|json=0", | |
| slice_id, | |
| frame.rung.label(), | |
| frame.symbols.len(), | |
| frame.nbytes, | |
| self.sha256.sha16_hex() | |
| )); | |
| } | |
| for (idx, modulus) in codec.primes.iter().enumerate() { | |
| let cumulative = &codec.primes[..=idx]; | |
| rows.push(format!("Q3DCYL|id={}|idx={}|coprime_modulus={}|blocks={}|capacity_bits_floor={}|residual_selector_bits={}|capacity_margin_bits_floor={}|shadow_clone=classical|json=0", slice_id, idx, modulus, self.shadows.residues[idx].len(), joint_capacity_bits_floor(cumulative).unwrap_or(0), residual_selector_bits_for(codec.block_bytes, cumulative).unwrap_or(128), signed_capacity_margin_bits_floor(codec.block_bytes, cumulative).unwrap_or(-128))); | |
| } | |
| for watcher in ["OMNISHANNON", "GNN", "REVERSE_GNN", "MTP1", "MTP2", "MTP3"] { | |
| rows.push(format!( | |
| "Q3DWATCH|id={}|watcher={}|role=edge_capacity_and_recovery_guard|host8={}|json=0", | |
| slice_id, watcher, self.host8_hex | |
| )); | |
| } | |
| rows | |
| } | |
| } | |
| // ------------------------------------------------------------ PIE pixels-first world slice lane | |
| /// A metatagged simulated-world particle rendered into a pixels-first slice. | |
| /// | |
| /// This is classical representation data, not physical quantum cloning. The tag/frequency fields | |
| /// are deterministic control labels used to render and re-render a slice byte-identically. | |
| pub struct TaggedParticle { | |
| pub x: u16, | |
| pub y: u16, | |
| pub z: u16, | |
| pub tag: u32, | |
| pub frequency: u16, | |
| pub intensity: u8, | |
| } | |
| /// A bounded pixels-first simulated-world slice. Its byte frame is the object projected into | |
| /// N coprime cylinders; sufficient cylinder shadows recover it exactly. | |
| pub struct PiePixelSlice { | |
| pub width: u16, | |
| pub height: u16, | |
| pub tick: u64, | |
| pub frequency: u16, | |
| pub pixels: Vec<u8>, | |
| } | |
| impl PiePixelSlice { | |
| pub fn new( | |
| width: u16, | |
| height: u16, | |
| tick: u64, | |
| frequency: u16, | |
| pixels: Vec<u8>, | |
| ) -> Result<Self, Held> { | |
| let expected = width as usize * height as usize; | |
| if width == 0 || height == 0 || expected == 0 || pixels.len() != expected { | |
| return Err(Held::InvalidSliceGeometry); | |
| } | |
| Ok(Self { | |
| width, | |
| height, | |
| tick, | |
| frequency, | |
| pixels, | |
| }) | |
| } | |
| pub fn from_particles( | |
| width: u16, | |
| height: u16, | |
| tick: u64, | |
| frequency: u16, | |
| particles: &[TaggedParticle], | |
| ) -> Result<Self, Held> { | |
| if width == 0 || height == 0 { | |
| return Err(Held::InvalidSliceGeometry); | |
| } | |
| let mut pixels = vec![0u8; width as usize * height as usize]; | |
| for p in particles { | |
| let x = (p.x % width) as usize; | |
| let y = (p.y % height) as usize; | |
| let idx = y * width as usize + x; | |
| let tag_mix = ((p.tag as u8) ^ (p.tag >> 8) as u8 ^ (p.z as u8)) & 0x1f; | |
| let freq_mix = ((p.frequency ^ frequency) & 0xff) as u8; | |
| pixels[idx] = pixels[idx].wrapping_add(p.intensity ^ tag_mix ^ freq_mix); | |
| } | |
| Self::new(width, height, tick, frequency, pixels) | |
| } | |
| pub fn to_bytes(&self) -> Vec<u8> { | |
| let mut out = Vec::with_capacity(18 + self.pixels.len()); | |
| out.extend_from_slice(b"PIE1"); | |
| out.extend_from_slice(&self.width.to_be_bytes()); | |
| out.extend_from_slice(&self.height.to_be_bytes()); | |
| out.extend_from_slice(&self.tick.to_be_bytes()); | |
| out.extend_from_slice(&self.frequency.to_be_bytes()); | |
| out.extend_from_slice(&self.pixels); | |
| out | |
| } | |
| pub fn from_bytes(bytes: &[u8]) -> Result<Self, Held> { | |
| if bytes.len() < 18 || &bytes[..4] != b"PIE1" { | |
| return Err(Held::InvalidSliceEncoding); | |
| } | |
| let width = u16::from_be_bytes([bytes[4], bytes[5]]); | |
| let height = u16::from_be_bytes([bytes[6], bytes[7]]); | |
| let tick = u64::from_be_bytes([ | |
| bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], | |
| ]); | |
| let frequency = u16::from_be_bytes([bytes[16], bytes[17]]); | |
| let pixels = bytes[18..].to_vec(); | |
| Self::new(width, height, tick, frequency, pixels) | |
| } | |
| /// Shell occupancy around the pixel-center. This is the discrete "sphere at frequency" view: | |
| /// same-radius pixels form one frequency shell in the bounded slice. | |
| pub fn frequency_shells(&self) -> Vec<FrequencyShell> { | |
| let cx2 = self.width as i32 - 1; | |
| let cy2 = self.height as i32 - 1; | |
| let mut shells: Vec<FrequencyShell> = Vec::new(); | |
| for y in 0..self.height as usize { | |
| for x in 0..self.width as usize { | |
| let dx2 = (x as i32 * 2) - cx2; | |
| let dy2 = (y as i32 * 2) - cy2; | |
| let radius2 = (dx2 * dx2 + dy2 * dy2) as u32; | |
| let idx = y * self.width as usize + x; | |
| match shells.iter_mut().find(|s| s.radius2 == radius2) { | |
| Some(s) => { | |
| s.pixels += 1; | |
| s.energy = s.energy.wrapping_add(self.pixels[idx] as u64); | |
| } | |
| None => shells.push(FrequencyShell { | |
| radius2, | |
| frequency: self.frequency, | |
| pixels: 1, | |
| energy: self.pixels[idx] as u64, | |
| }), | |
| } | |
| } | |
| } | |
| shells.sort_by_key(|s| s.radius2); | |
| shells | |
| } | |
| } | |
| /// The minimal pixels-first selector/check unit: one pixel plus the Q-PRISM context needed to | |
| /// re-address and verify it. It is not a raw payload bit; it is a checked representation pointer. | |
| pub struct OmnibitPixel { | |
| pub x: u16, | |
| pub y: u16, | |
| pub tick: u64, | |
| pub frequency: u16, | |
| pub value: u8, | |
| pub host8_hex: String, | |
| pub residual_selector_bits: u32, | |
| pub capacity_margin_bits_floor: i32, | |
| } | |
| impl OmnibitPixel { | |
| pub fn from_slice( | |
| slice: &PiePixelSlice, | |
| x: u16, | |
| y: u16, | |
| projection: &PieWorldProjection, | |
| codec: &MultiCylinder, | |
| selected_cylinders: &[usize], | |
| ) -> Result<Self, Held> { | |
| if x >= slice.width || y >= slice.height { | |
| return Err(Held::InvalidSliceGeometry); | |
| } | |
| let idx = y as usize * slice.width as usize + x as usize; | |
| Ok(Self { | |
| x, | |
| y, | |
| tick: slice.tick, | |
| frequency: slice.frequency, | |
| value: slice.pixels[idx], | |
| host8_hex: projection.qprism.host8_hex.clone(), | |
| residual_selector_bits: codec.residual_selector_bits(selected_cylinders)?, | |
| capacity_margin_bits_floor: codec | |
| .signed_capacity_margin_bits_floor(selected_cylinders)?, | |
| }) | |
| } | |
| pub fn hbp_row(&self, slice_id: &str) -> String { | |
| format!( | |
| "OMNIBITPIXEL|id={}|x={}|y={}|tick={}|frequency={}|value={}|host8={}|residual_selector_bits={}|capacity_margin_bits_floor={}|role=pixel_selector_check_unit|body_in_row=0|json=0", | |
| slice_id, | |
| self.x, | |
| self.y, | |
| self.tick, | |
| self.frequency, | |
| self.value, | |
| self.host8_hex, | |
| self.residual_selector_bits, | |
| self.capacity_margin_bits_floor | |
| ) | |
| } | |
| } | |
| pub struct FrequencyShell { | |
| pub radius2: u32, | |
| pub frequency: u16, | |
| pub pixels: usize, | |
| pub energy: u64, | |
| } | |
| /// Deterministic LeWorld-style latent rule for a classical simulated universe. | |
| /// | |
| /// If the state and rule are known, future and retrospective slices are computed byte-identically. | |
| /// If new entropy enters, this type is the wrong model and the caller must Hold. | |
| pub struct LeWorldRule { | |
| pub dx: i16, | |
| pub dy: i16, | |
| pub phase_delta: u16, | |
| pub xor_key: u8, | |
| } | |
| impl LeWorldRule { | |
| pub fn step(&self, slice: &PiePixelSlice) -> Result<PiePixelSlice, Held> { | |
| let w = slice.width as usize; | |
| let h = slice.height as usize; | |
| let next_tick = slice.tick.wrapping_add(1); | |
| let next_frequency = slice.frequency.wrapping_add(self.phase_delta); | |
| let mut out = vec![0u8; slice.pixels.len()]; | |
| for y in 0..h { | |
| for x in 0..w { | |
| let dst_x = wrap_add(x, self.dx, w); | |
| let dst_y = wrap_add(y, self.dy, h); | |
| let src_idx = y * w + x; | |
| let dst_idx = dst_y * w + dst_x; | |
| out[dst_idx] = slice.pixels[src_idx] ^ self.mask(x, y, slice.tick, slice.frequency); | |
| } | |
| } | |
| PiePixelSlice::new(slice.width, slice.height, next_tick, next_frequency, out) | |
| } | |
| pub fn backstep(&self, slice: &PiePixelSlice) -> Result<PiePixelSlice, Held> { | |
| let w = slice.width as usize; | |
| let h = slice.height as usize; | |
| let prev_tick = slice.tick.wrapping_sub(1); | |
| let prev_frequency = slice.frequency.wrapping_sub(self.phase_delta); | |
| let mut out = vec![0u8; slice.pixels.len()]; | |
| for y in 0..h { | |
| for x in 0..w { | |
| let dst_x = wrap_add(x, self.dx, w); | |
| let dst_y = wrap_add(y, self.dy, h); | |
| let dst_idx = dst_y * w + dst_x; | |
| let src_idx = y * w + x; | |
| out[src_idx] = slice.pixels[dst_idx] ^ self.mask(x, y, prev_tick, prev_frequency); | |
| } | |
| } | |
| PiePixelSlice::new(slice.width, slice.height, prev_tick, prev_frequency, out) | |
| } | |
| fn mask(&self, x: usize, y: usize, tick: u64, frequency: u16) -> u8 { | |
| let t = (tick as u8).wrapping_mul(17); | |
| let f = (frequency as u8).wrapping_mul(31); | |
| self.xor_key ^ t ^ f ^ (x as u8).wrapping_mul(3) ^ (y as u8).wrapping_mul(5) | |
| } | |
| } | |
| fn wrap_add(value: usize, delta: i16, modulus: usize) -> usize { | |
| let m = modulus as i32; | |
| ((value as i32 + delta as i32).rem_euclid(m)) as usize | |
| } | |
| pub struct PieWorldProjection { | |
| pub qprism: QPrismSlice3d, | |
| pub shells: Vec<FrequencyShell>, | |
| } | |
| impl PieWorldProjection { | |
| pub fn project(slice: &PiePixelSlice, codec: &MultiCylinder) -> Self { | |
| Self { | |
| qprism: QPrismSlice3d::project(&slice.to_bytes(), codec), | |
| shells: slice.frequency_shells(), | |
| } | |
| } | |
| pub fn recover_current( | |
| &self, | |
| codec: &MultiCylinder, | |
| indices: &[usize], | |
| ) -> Result<PiePixelSlice, Held> { | |
| let bytes = codec.recover_from(&self.qprism.shadows, indices)?; | |
| PiePixelSlice::from_bytes(&bytes) | |
| } | |
| pub fn predict_next( | |
| &self, | |
| rule: &LeWorldRule, | |
| codec: &MultiCylinder, | |
| indices: &[usize], | |
| ) -> Result<PiePixelSlice, Held> { | |
| let current = self.recover_current(codec, indices)?; | |
| rule.step(¤t) | |
| } | |
| pub fn predict_previous( | |
| &self, | |
| rule: &LeWorldRule, | |
| codec: &MultiCylinder, | |
| indices: &[usize], | |
| ) -> Result<PiePixelSlice, Held> { | |
| let current = self.recover_current(codec, indices)?; | |
| rule.backstep(¤t) | |
| } | |
| pub fn hbp_rows(&self, codec: &MultiCylinder, slice_id: &str) -> Vec<String> { | |
| let mut rows = self.qprism.hbp_rows(codec, slice_id); | |
| rows.push(format!( | |
| "PIEWORLD|id={}|shells={}|sphere_view=frequency_shells|sha16={}|body_in_row=0|json=0", | |
| slice_id, | |
| self.shells.len(), | |
| self.qprism.sha256.sha16_hex() | |
| )); | |
| for (idx, shell) in self.shells.iter().take(16).enumerate() { | |
| rows.push(format!( | |
| "PIESHELL|id={}|idx={}|radius2={}|frequency={}|pixels={}|energy={}|json=0", | |
| slice_id, idx, shell.radius2, shell.frequency, shell.pixels, shell.energy | |
| )); | |
| } | |
| for watcher in ["LEWORLD", "PIXELS_FIRST", "PIE_SHADOW_ROOF"] { | |
| rows.push(format!( | |
| "PIEWATCH|id={}|watcher={}|role=deterministic_slice_prediction_or_hold|host8={}|json=0", | |
| slice_id, watcher, self.qprism.host8_hex | |
| )); | |
| } | |
| rows | |
| } | |
| } | |
| // ------------------------------------------------------------ DBBH -> DBWH watcher gate | |
| pub enum WatcherKind { | |
| OmniShannon, | |
| GnnForward, | |
| ReverseGnn, | |
| Mtp1, | |
| Mtp2, | |
| Mtp3, | |
| } | |
| impl WatcherKind { | |
| pub fn label(self) -> &'static str { | |
| match self { | |
| WatcherKind::OmniShannon => "OMNISHANNON", | |
| WatcherKind::GnnForward => "GNN_FORWARD", | |
| WatcherKind::ReverseGnn => "REVERSE_GNN", | |
| WatcherKind::Mtp1 => "MTP1", | |
| WatcherKind::Mtp2 => "MTP2", | |
| WatcherKind::Mtp3 => "MTP3", | |
| } | |
| } | |
| } | |
| pub const DEFAULT_WATCHERS: [WatcherKind; 6] = [ | |
| WatcherKind::OmniShannon, | |
| WatcherKind::GnnForward, | |
| WatcherKind::ReverseGnn, | |
| WatcherKind::Mtp1, | |
| WatcherKind::Mtp2, | |
| WatcherKind::Mtp3, | |
| ]; | |
| pub struct WatcherVerdict { | |
| pub watcher: WatcherKind, | |
| pub passed: bool, | |
| pub detail: &'static str, | |
| } | |
| pub struct WatcherGateReceipt { | |
| pub slice_id: String, | |
| pub verified_clone: PiePixelSlice, | |
| pub black_host8_hex: String, | |
| pub white_host8_hex: String, | |
| pub selected_cylinders: Vec<usize>, | |
| pub residual_selector_bits: u32, | |
| pub capacity_margin_bits_floor: i32, | |
| pub watcher_verdicts: Vec<WatcherVerdict>, | |
| pub hallucinations_caught: u32, | |
| pub undetected_bound_denom_log2_floor: u32, | |
| } | |
| impl WatcherGateReceipt { | |
| pub fn hbp_rows(&self) -> Vec<String> { | |
| let mut rows = Vec::new(); | |
| rows.push(format!( | |
| "WATCHGATE|id={}|black_host8={}|white_host8={}|verified_clone=1|selected={}|residual_selector_bits={}|capacity_margin_bits_floor={}|hallucinations_caught={}|undetected_bound_denom_log2_floor={}|body_in_row=0|json=0", | |
| self.slice_id, | |
| self.black_host8_hex, | |
| self.white_host8_hex, | |
| join_usize_dot(&self.selected_cylinders), | |
| self.residual_selector_bits, | |
| self.capacity_margin_bits_floor, | |
| self.hallucinations_caught, | |
| self.undetected_bound_denom_log2_floor | |
| )); | |
| for verdict in &self.watcher_verdicts { | |
| rows.push(format!( | |
| "WATCHVERDICT|id={}|watcher={}|passed={}|detail={}|json=0", | |
| self.slice_id, | |
| verdict.watcher.label(), | |
| u8::from(verdict.passed), | |
| verdict.detail | |
| )); | |
| } | |
| rows | |
| } | |
| } | |
| pub struct WatcherGate; | |
| impl WatcherGate { | |
| pub fn verify_projection( | |
| slice_id: &str, | |
| projection: &PieWorldProjection, | |
| codec: &MultiCylinder, | |
| selected_cylinders: &[usize], | |
| ) -> Result<WatcherGateReceipt, Held> { | |
| let recovered = projection.recover_current(codec, selected_cylinders)?; | |
| let white_projection = PieWorldProjection::project(&recovered, codec); | |
| if white_projection.qprism.sha256 != projection.qprism.sha256 { | |
| return Err(Held::WatcherDisagreement); | |
| } | |
| if white_projection.qprism.shadows != projection.qprism.shadows { | |
| return Err(Held::WatcherDisagreement); | |
| } | |
| if white_projection.shells != projection.shells { | |
| return Err(Held::WatcherDisagreement); | |
| } | |
| let residual_selector_bits = codec.residual_selector_bits(selected_cylinders)?; | |
| let capacity_margin_bits_floor = | |
| codec.signed_capacity_margin_bits_floor(selected_cylinders)?; | |
| let watcher_verdicts = DEFAULT_WATCHERS | |
| .iter() | |
| .map(|&watcher| WatcherVerdict { | |
| watcher, | |
| passed: true, | |
| detail: match watcher { | |
| WatcherKind::OmniShannon => "capacity_ledger_ok", | |
| WatcherKind::GnnForward => "black_to_white_projection_ok", | |
| WatcherKind::ReverseGnn => "white_to_black_recompression_ok", | |
| WatcherKind::Mtp1 => "pixel_slice_observer_ok", | |
| WatcherKind::Mtp2 => "frequency_shell_observer_ok", | |
| WatcherKind::Mtp3 => "cylinder_residue_observer_ok", | |
| }, | |
| }) | |
| .collect::<Vec<_>>(); | |
| let undetected_bound_denom_log2_floor = (capacity_margin_bits_floor.max(0) as u32) | |
| .saturating_add(DEFAULT_WATCHERS.len() as u32); | |
| Ok(WatcherGateReceipt { | |
| slice_id: slice_id.to_string(), | |
| verified_clone: recovered, | |
| black_host8_hex: projection.qprism.host8_hex.clone(), | |
| white_host8_hex: white_projection.qprism.host8_hex, | |
| selected_cylinders: selected_cylinders.to_vec(), | |
| residual_selector_bits, | |
| capacity_margin_bits_floor, | |
| watcher_verdicts, | |
| hallucinations_caught: 0, | |
| undetected_bound_denom_log2_floor, | |
| }) | |
| } | |
| pub fn verify_slice( | |
| slice_id: &str, | |
| slice: &PiePixelSlice, | |
| codec: &MultiCylinder, | |
| selected_cylinders: &[usize], | |
| ) -> Result<WatcherGateReceipt, Held> { | |
| let projection = PieWorldProjection::project(slice, codec); | |
| Self::verify_projection(slice_id, &projection, codec, selected_cylinders) | |
| } | |
| pub fn detect_tampered_projection( | |
| slice_id: &str, | |
| projection: &PieWorldProjection, | |
| codec: &MultiCylinder, | |
| selected_cylinders: &[usize], | |
| ) -> Result<WatcherGateReceipt, Held> { | |
| match Self::verify_projection(slice_id, projection, codec, selected_cylinders) { | |
| Ok(receipt) => Ok(receipt), | |
| Err(Held::InconsistentResidue | Held::WatcherDisagreement) => Ok(WatcherGateReceipt { | |
| slice_id: slice_id.to_string(), | |
| verified_clone: PiePixelSlice::new(1, 1, 0, 0, vec![0])?, | |
| black_host8_hex: projection.qprism.host8_hex.clone(), | |
| white_host8_hex: "HELD".to_string(), | |
| selected_cylinders: selected_cylinders.to_vec(), | |
| residual_selector_bits: codec | |
| .residual_selector_bits(selected_cylinders) | |
| .unwrap_or(128), | |
| capacity_margin_bits_floor: codec | |
| .signed_capacity_margin_bits_floor(selected_cylinders) | |
| .unwrap_or(-128), | |
| watcher_verdicts: vec![WatcherVerdict { | |
| watcher: WatcherKind::ReverseGnn, | |
| passed: false, | |
| detail: "roundtrip_disagreement_held", | |
| }], | |
| hallucinations_caught: 1, | |
| undetected_bound_denom_log2_floor: 0, | |
| }), | |
| Err(e) => Err(e), | |
| } | |
| } | |
| } | |
| fn join_usize_dot(values: &[usize]) -> String { | |
| let mut out = String::new(); | |
| for (i, value) in values.iter().enumerate() { | |
| if i > 0 { | |
| out.push('.'); | |
| } | |
| out.push_str(&value.to_string()); | |
| } | |
| out | |
| } | |
| // ============================================================ unit tests | |
| mod unit { | |
| use super::*; | |
| fn one_shadow_is_lossy_non_injective() { | |
| // x and x+p cast the SAME shadow -> a single shadow cannot recover x | |
| let p = TwoShadow::P1; | |
| let x = 123_456_789u128; | |
| assert_eq!(shadow(x, p), shadow(x + p as u128, p)); | |
| assert_eq!(shadow(x, p), shadow(x + 7 * p as u128, p)); | |
| } | |
| fn two_shadows_recover_exactly_no_store() { | |
| let (p1, p2) = (TwoShadow::P1, TwoShadow::P2); | |
| let range = 1u128 << 48; | |
| for x in [0u128, 1, 255, 1 << 24, (1u128 << 48) - 1, 987_654_321_012] { | |
| let s1 = shadow(x, p1); | |
| let s2 = shadow(x, p2); | |
| assert_eq!(two_shadow_recover(s1, p1, s2, p2, range), Ok(x), "x={x}"); | |
| } | |
| } | |
| fn insufficient_joint_capacity_is_held_shannon_wall() { | |
| // two tiny primes cannot jointly carry a 48-bit block | |
| let (p1, p2) = (251u64, 257u64); // product 64507 << 2^48 | |
| let range = 1u128 << 48; | |
| assert_eq!( | |
| two_shadow_recover(3, p1, 5, p2, range), | |
| Err(Held::InsufficientJointCapacity) | |
| ); | |
| } | |
| fn bytes_roundtrip_recovers_without_store() { | |
| let ts = TwoShadow::new(); | |
| assert!(ts.sufficient()); | |
| for data in [ | |
| &b""[..], | |
| &b"a"[..], | |
| &b"double binary black hole"[..], | |
| &vec![0xABu8; 200][..], | |
| &(0..255u16).map(|i| (i * 7) as u8).collect::<Vec<u8>>()[..], | |
| ] { | |
| let sh = ts.project(data); | |
| assert_eq!(ts.recover(&sh).unwrap(), data, "len={}", data.len()); | |
| } | |
| } | |
| fn neither_pole_alone_can_reconstruct() { | |
| // party A holds only shadow_a, party B only shadow_b. A single pole leaves each block | |
| // ambiguous across ~2^23 candidates -> reconstruction needs BOTH (the double-binary consent). | |
| let ts = TwoShadow::new(); | |
| let data = b"only the two poles together recover this"; | |
| let sh = ts.project(data); | |
| // A alone: try to recover treating shadow_b as unknown/zero -> wrong bytes | |
| let a_only = Shadows { | |
| shadow_a: sh.shadow_a.clone(), | |
| shadow_b: vec![0; sh.shadow_b.len()], | |
| orig_len: sh.orig_len, | |
| }; | |
| assert_ne!( | |
| ts.recover(&a_only).unwrap(), | |
| data, | |
| "one pole must NOT reconstruct" | |
| ); | |
| // both poles: exact | |
| assert_eq!(ts.recover(&sh).unwrap(), data); | |
| } | |
| } | |