diff --git a/2-Search-Space/rust/Cargo.lock b/2-Search-Space/rust/Cargo.lock new file mode 100644 index 00000000..e2e5c24a --- /dev/null +++ b/2-Search-Space/rust/Cargo.lock @@ -0,0 +1,346 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "angrysphinx-gates" +version = "0.1.0" +dependencies = [ + "clap", + "serde_json", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "famm-receipts" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "serde_json", + "sha2", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/2-Search-Space/rust/Cargo.toml b/2-Search-Space/rust/Cargo.toml new file mode 100644 index 00000000..488616d1 --- /dev/null +++ b/2-Search-Space/rust/Cargo.toml @@ -0,0 +1,9 @@ +[workspace] +members = ["crates/*"] +resolver = "2" + +[workspace.package] +version = "0.1.0" +edition = "2021" +authors = ["Research Stack Team"] +license = "Apache-2.0" diff --git a/2-Search-Space/rust/crates/angrysphinx-gates/Cargo.toml b/2-Search-Space/rust/crates/angrysphinx-gates/Cargo.toml new file mode 100644 index 00000000..f10afb50 --- /dev/null +++ b/2-Search-Space/rust/crates/angrysphinx-gates/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "angrysphinx-gates" +version.workspace = true +edition.workspace = true +authors.workspace = true +description = "Rust ports of first-party AngrySphinx gate prototypes" +license.workspace = true + +[dependencies] +clap = { version = "4.5", features = ["derive"] } +serde_json = "1.0" + +[[bin]] +name = "dynamic-lut-slotter" +path = "src/bin/dynamic_lut_slotter.rs" diff --git a/2-Search-Space/rust/crates/angrysphinx-gates/src/bin/dynamic_lut_slotter.rs b/2-Search-Space/rust/crates/angrysphinx-gates/src/bin/dynamic_lut_slotter.rs new file mode 100644 index 00000000..f8395c2e --- /dev/null +++ b/2-Search-Space/rust/crates/angrysphinx-gates/src/bin/dynamic_lut_slotter.rs @@ -0,0 +1,351 @@ +use clap::Parser; +use serde_json::{json, Value}; + +#[derive(Clone, Copy)] +struct WorkloadProfile { + name: &'static str, + slot: u8, + default_domain: u8, + default_scalar: u8, + mountain_range: &'static str, +} + +#[derive(Clone)] +struct OmniToken { + shell: String, + workload: &'static str, + mountain_range: &'static str, + slot: u8, + domain: u8, + scalar: u8, + avmr_signal: u8, + s3c_emit: bool, + s3c_score: u8, + ammr_safe: bool, +} + +#[derive(Parser)] +#[command(about = "Dynamic Omnitoken LUT slot selector for workload-shaped tiny tokens.")] +struct Args { + #[arg(long, default_value = "ethernet")] + shell: String, + #[arg(long, default_value = "angry_sphinx")] + workload: String, + #[arg(long, default_value_t = 10, value_parser = clap::value_parser!(u8).range(0..=100))] + pressure: u8, + #[arg(long = "partial-budget", default_value_t = 32)] + partial_budget: u8, + #[arg(long, value_parser = parse_byte)] + scalar: Option, + #[arg(long)] + demo: bool, + #[arg(long)] + jsonl: bool, +} + +const RECOVERY: WorkloadProfile = WorkloadProfile { + name: "recovery", + slot: 0x01, + default_domain: 0x0D, + default_scalar: 0x01, + mountain_range: "root_mountain", +}; + +const ANGRY_SPHINX: WorkloadProfile = WorkloadProfile { + name: "angry_sphinx", + slot: 0x02, + default_domain: 0x0F, + default_scalar: 0x01, + mountain_range: "frustration_range", +}; + +const STANDARDS_REGISTRY: WorkloadProfile = WorkloadProfile { + name: "standards_registry", + slot: 0x20, + default_domain: 0x10, + default_scalar: 0x01, + mountain_range: "public_basis_range", +}; + +const CRYPTO_MEV_RESEARCH: WorkloadProfile = WorkloadProfile { + name: "crypto_mev_research", + slot: 0x30, + default_domain: 0x31, + default_scalar: 0x01, + mountain_range: "adversarial_flow_range", +}; + +const IBMII_ETHERNET: WorkloadProfile = WorkloadProfile { + name: "ibmii_ethernet", + slot: 0x40, + default_domain: 0x0D, + default_scalar: 0x01, + mountain_range: "legacy_shell_range", +}; + +const ISO_PREPASS: WorkloadProfile = WorkloadProfile { + name: "iso_prepass", + slot: 0x50, + default_domain: 0x51, + default_scalar: 0x01, + mountain_range: "symbol_basis_range", +}; + +fn parse_byte(value: &str) -> Result { + let parsed = if let Some(hex) = value + .strip_prefix("0x") + .or_else(|| value.strip_prefix("0X")) + { + u16::from_str_radix(hex, 16).map_err(|err| err.to_string())? + } else { + value.parse::().map_err(|err| err.to_string())? + }; + u8::try_from(parsed).map_err(|_| "--scalar must fit in one byte".to_string()) +} + +fn select_profile(workload: &str, pressure: u8) -> WorkloadProfile { + if pressure >= 90 && workload != "recovery" { + return RECOVERY; + } + match workload { + "recovery" => RECOVERY, + "angry_sphinx" => ANGRY_SPHINX, + "standards_registry" => STANDARDS_REGISTRY, + "crypto_mev_research" => CRYPTO_MEV_RESEARCH, + "ibmii_ethernet" => IBMII_ETHERNET, + "iso_prepass" => ISO_PREPASS, + _ => ANGRY_SPHINX, + } +} + +fn avmr_signal(shell: &str, workload: &str, pressure: u8) -> u8 { + let text = format!("{shell}:{workload}"); + let shell_mass = text + .as_bytes() + .iter() + .enumerate() + .fold(0u16, |acc, (idx, byte)| { + acc.wrapping_add(((idx as u16) + 1) * (*byte as u16)) & 0xFF + }); + let pressure_penalty = u16::from(pressure).saturating_mul(2).min(200); + let signal = i32::from(shell_mass) - i32::from(pressure_penalty) + 64; + signal.clamp(0, 255) as u8 +} + +fn s3c_partial_gate(slot: u8, domain: u8, scalar: u8, budget: u8) -> (bool, u8) { + let n = ((slot as u32) << 8) | ((domain as u32) << 4) | u32::from(scalar & 0x0F); + let k = (n as f64).sqrt() as u32; + let a = n - k * k; + let b = (k + 1) * (k + 1) - n; + let mass = a * b; + let width = (a + b + 1).max(1); + let echo = u32::from((slot ^ domain).wrapping_add(scalar)); + let contact_a = (a + echo) % 3 != 0; + let contact_c = (b + echo) % 5 != 0; + let score = (mass % 256) as i32 + i32::from(budget) - width as i32; + ( + contact_a && contact_c && score > 0, + score.clamp(0, 255) as u8, + ) +} + +fn ammr_allows(profile: WorkloadProfile, signal: u8, pressure: u8, s3c_emit: bool) -> bool { + if profile.name == "angry_sphinx" || profile.name == "recovery" { + return true; + } + if pressure >= 90 { + return false; + } + signal >= 24 && s3c_emit +} + +fn make_token( + shell: &str, + workload: &str, + pressure: u8, + scalar: Option, + partial_budget: u8, +) -> OmniToken { + let mut profile = select_profile(workload, pressure); + let mut signal = avmr_signal(shell, profile.name, pressure); + let mut candidate_scalar = scalar.unwrap_or(profile.default_scalar); + let (mut s3c_emit, mut s3c_score) = s3c_partial_gate( + profile.slot, + profile.default_domain, + candidate_scalar, + partial_budget, + ); + let mut safe = ammr_allows(profile, signal, pressure, s3c_emit); + + if !safe && profile.name != "recovery" { + profile = if pressure >= 90 { + RECOVERY + } else { + ANGRY_SPHINX + }; + signal = avmr_signal(shell, profile.name, pressure); + candidate_scalar = scalar.unwrap_or(profile.default_scalar); + (s3c_emit, s3c_score) = s3c_partial_gate( + profile.slot, + profile.default_domain, + candidate_scalar, + partial_budget, + ); + safe = ammr_allows(profile, signal, pressure, s3c_emit); + } + + OmniToken { + shell: shell.to_string(), + workload: profile.name, + mountain_range: profile.mountain_range, + slot: profile.slot, + domain: profile.default_domain, + scalar: candidate_scalar, + avmr_signal: signal, + s3c_emit, + s3c_score, + ammr_safe: safe, + } +} + +fn admit(token: &OmniToken) -> &'static str { + match (token.slot, token.domain, token.scalar) { + (0x01, 0x0D, 0x01) => "recover", + (0x02, 0x0F, 0x01) => "angry_sphinx_challenge", + (0x20, 0x10, 0x01) => "index_standard_surface", + (0x20, 0x10, 0x02) => "refresh_registry_pointer", + (0x30, 0x31, 0x01) => "classify_mempool_surface", + (0x30, 0x31, 0x02) => "route_mev_research_candidate", + (0x40, 0x0D, 0x01) => "recover_from_ethernet_shell", + (0x50, 0x51, 0x01) => "apply_iso_symbol_basis", + _ => "refuse", + } +} + +fn event(token: &OmniToken, action: &str) -> Value { + json!({ + "v": "hs-jsonl-0.1", + "id": format!("omni-lut:{}:0x{:02X}:0x{:02X}", token.workload, token.slot, token.scalar), + "op": if action.starts_with("recover") { "recover" } else { "route" }, + "surface": { + "class": "node", + "kind": "omnisurface.dynamic_lut", + "caps": ["recover", "route", "attest"] + }, + "gcl": { + "admission": if action != "refuse" { "admitted" } else { "refused" }, + "capability_tier": "T1_8kb", + "invariant": "workload_slot_before_lut_expansion", + "refusal_code": if action != "refuse" { "none" } else { "op_not_supported" } + }, + "omni": { + "shell": token.shell, + "workload_profile": token.workload, + "mountain_range": token.mountain_range, + "lut_slot": format!("0x{:02X}", token.slot), + "domain": format!("0x{:02X}", token.domain), + "scalar": format!("0x{:02X}", token.scalar), + "avmr_signal": token.avmr_signal, + "s3c_emit": token.s3c_emit, + "s3c_score": token.s3c_score, + "ammr_safe": token.ammr_safe, + "angry_sphinx_default": token.workload == "angry_sphinx", + "action": action + }, + "privacy": { + "tier": "internal", + "retention": "cache", + "export": "deny", + "redaction": "none" + } + }) +} + +fn run_cases( + cases: Vec<(&str, &str, u8, Option)>, + emit_jsonl: bool, + partial_budget: u8, +) -> i32 { + let mut refused = 0; + for (shell, workload, pressure, scalar) in cases { + let token = make_token(shell, workload, pressure, scalar, partial_budget); + let action = admit(&token); + refused += i32::from(action == "refuse"); + if emit_jsonl { + println!( + "{}", + serde_json::to_string(&event(&token, action)).expect("json event") + ); + } else { + let raw = format!("{:02x}{:02x}{:02x}", token.slot, token.domain, token.scalar); + println!( + "shell={} workload={} mountain={} signal={} s3c_emit={} s3c_score={} ammr_safe={} slot=0x{:02X} domain=0x{:02X} scalar=0x{:02X} bytes={} action={}", + token.shell, + token.workload, + token.mountain_range, + token.avmr_signal, + i32::from(token.s3c_emit), + token.s3c_score, + i32::from(token.ammr_safe), + token.slot, + token.domain, + token.scalar, + raw, + action + ); + } + } + i32::from(refused > 0) +} + +fn main() { + let args = Args::parse(); + let code = if args.demo { + run_cases( + vec![ + ("unknown-shell", "unknown", 10, None), + ("ethernet", "ibmii_ethernet", 20, None), + ("ipv923u", "standards_registry", 25, None), + ("onion", "crypto_mev_research", 40, None), + ("serial", "iso_prepass", 15, None), + ("tcp", "crypto_mev_research", 95, None), + ], + args.jsonl, + args.partial_budget, + ) + } else { + let token = make_token( + &args.shell, + &args.workload, + args.pressure, + args.scalar, + args.partial_budget, + ); + let action = admit(&token); + if args.jsonl { + println!( + "{}", + serde_json::to_string(&event(&token, action)).expect("json event") + ); + } else { + let raw = format!("{:02x}{:02x}{:02x}", token.slot, token.domain, token.scalar); + println!( + "shell={} workload={} mountain={} signal={} s3c_emit={} s3c_score={} ammr_safe={} slot=0x{:02X} domain=0x{:02X} scalar=0x{:02X} bytes={} action={}", + token.shell, + token.workload, + token.mountain_range, + token.avmr_signal, + i32::from(token.s3c_emit), + token.s3c_score, + i32::from(token.ammr_safe), + token.slot, + token.domain, + token.scalar, + raw, + action + ); + } + i32::from(action == "refuse") + }; + std::process::exit(code); +} diff --git a/2-Search-Space/rust/crates/famm-receipts/Cargo.toml b/2-Search-Space/rust/crates/famm-receipts/Cargo.toml new file mode 100644 index 00000000..17fe216a --- /dev/null +++ b/2-Search-Space/rust/crates/famm-receipts/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "famm-receipts" +version.workspace = true +edition.workspace = true +authors.workspace = true +description = "Rust ports of first-party FAMM receipt runners" +license.workspace = true + +[dependencies] +anyhow = "1.0" +clap = { version = "4.5", features = ["derive"] } +serde_json = "1.0" +sha2 = "0.10" + +[[bin]] +name = "sidon-famm-map" +path = "src/bin/sidon_famm_map.rs" + +[[bin]] +name = "anti-famm-adversary" +path = "src/bin/anti_famm_adversary.rs" diff --git a/2-Search-Space/rust/crates/famm-receipts/src/bin/anti_famm_adversary.rs b/2-Search-Space/rust/crates/famm-receipts/src/bin/anti_famm_adversary.rs new file mode 100644 index 00000000..884b8550 --- /dev/null +++ b/2-Search-Space/rust/crates/famm-receipts/src/bin/anti_famm_adversary.rs @@ -0,0 +1,165 @@ +use anyhow::{Context, Result}; +use clap::Parser; +use famm_receipts::{clamp01, sha256_json}; +use serde_json::{json, Value}; +use std::fs; +use std::path::PathBuf; + +#[derive(Parser)] +struct Args { + #[arg(long)] + config: PathBuf, + #[arg(long)] + out: PathBuf, +} + +fn number(test: &Value, key: &str) -> f64 { + clamp01(test.get(key).and_then(Value::as_f64).unwrap_or(0.0)) +} + +fn score_anti_famm(test: &Value) -> Value { + let invisible = number(test, "projection_invisibility"); + let target_change = number(test, "target_behavior_change"); + let invariant_fail = number(test, "invariant_failure"); + let false_scar = number(test, "false_scar_evidence"); + let residual = number(test, "hidden_residual"); + let risk = clamp01( + 0.30 * invisible + + 0.30 * target_change + + 0.20 * invariant_fail + + 0.10 * false_scar + + 0.10 * residual, + ); + let test_hash = sha256_json(test); + json!({ + "test_id": test.get("id").and_then(Value::as_str).map(str::to_owned).unwrap_or_else(|| test_hash[..12].to_string()), + "type": "anti_famm", + "risk": risk, + "decision": if risk >= 0.5 { "WARDEN_BLOCK_OR_REOPEN" } else { "PASS_ADVERSARY_CHECK" }, + "test_hash": test_hash, + "summary": { + "projection_invisibility": invisible, + "target_behavior_change": target_change, + "invariant_failure": invariant_fail, + "false_scar_evidence": false_scar, + "hidden_residual": residual + } + }) +} + +fn score_anti_braid(test: &Value) -> Value { + let order = number(test, "braid_order_residual"); + let alias = number(test, "receipt_alias_risk"); + let fake = number(test, "fake_receipt_risk"); + let toxic = number(test, "toxic_recombination_risk"); + let scar_mask = number(test, "scar_masking_risk"); + let local_global = number(test, "local_pass_global_fail"); + let risk = clamp01( + 0.20 * order + + 0.20 * alias + + 0.15 * fake + + 0.15 * toxic + + 0.15 * scar_mask + + 0.15 * local_global, + ); + let test_hash = sha256_json(test); + json!({ + "test_id": test.get("id").and_then(Value::as_str).map(str::to_owned).unwrap_or_else(|| test_hash[..12].to_string()), + "type": "anti_braidstorm", + "risk": risk, + "decision": if risk >= 0.5 { "WARDEN_BLOCK_OR_REOPEN" } else { "PASS_ADVERSARY_CHECK" }, + "test_hash": test_hash, + "summary": { + "braid_order_residual": order, + "receipt_alias_risk": alias, + "fake_receipt_risk": fake, + "toxic_recombination_risk": toxic, + "scar_masking_risk": scar_mask, + "local_pass_global_fail": local_global + } + }) +} + +fn run(config: &Value) -> Value { + let anti_famm = config + .get("anti_famm_tests") + .and_then(Value::as_array) + .map(|tests| tests.iter().map(score_anti_famm).collect::>()) + .unwrap_or_default(); + let anti_braid = config + .get("anti_braidstorm_tests") + .and_then(Value::as_array) + .map(|tests| tests.iter().map(score_anti_braid).collect::>()) + .unwrap_or_default(); + + let all_tests = anti_famm + .iter() + .chain(anti_braid.iter()) + .cloned() + .collect::>(); + let blocked = all_tests + .iter() + .filter(|test| test["decision"] == "WARDEN_BLOCK_OR_REOPEN") + .count(); + let max_risk = all_tests + .iter() + .filter_map(|test| test["risk"].as_f64()) + .fold(0.0, f64::max); + let test_hashes = all_tests + .iter() + .map(|test| test["test_hash"].clone()) + .collect::>(); + + let mut receipt = json!({ + "receipt_type": "famm_adversarial_duals_receipt", + "schema_version": "0.1.0", + "target": config.get("target").cloned().unwrap_or_else(|| json!({})), + "anti_famm_results": anti_famm, + "anti_braidstorm_results": anti_braid, + "summary": { + "test_count": all_tests.len(), + "blocked_or_reopened_count": blocked, + "max_risk": max_risk + }, + "warden_decision": if blocked > 0 { "BLOCK_OR_REOPEN_ROUTE" } else { "ALLOW_PROMOTION_CANDIDATE" }, + "nuvmap": { + "target_hash": sha256_json(config.get("target").unwrap_or(&json!({}))), + "test_hashes": test_hashes, + "adversarial_dual_hash": sha256_json(&json!(all_tests.iter().map(|test| test["test_hash"].clone()).collect::>())) + }, + "no_drift_boundary": "Anti-FAMM and Anti-BraidStorm expose adversarial failure modes. Passing these checks is not a global proof by itself." + }); + let hash = sha256_json(&receipt); + receipt["receipt_hash"] = json!(hash); + receipt +} + +fn main() -> Result<()> { + let args = Args::parse(); + let config_text = fs::read_to_string(&args.config) + .with_context(|| format!("failed to read {}", args.config.display()))?; + let config: Value = serde_json::from_str(&config_text) + .with_context(|| format!("failed to parse {}", args.config.display()))?; + let receipt = run(&config); + + if let Some(parent) = args.out.parent() { + fs::create_dir_all(parent)?; + } + fs::write(&args.out, serde_json::to_string_pretty(&receipt)?)?; + + println!("Wrote {}", args.out.display()); + println!("Tests: {}", receipt["summary"]["test_count"]); + println!( + "Blocked/reopened: {}", + receipt["summary"]["blocked_or_reopened_count"] + ); + println!( + "Warden decision: {}", + receipt["warden_decision"].as_str().unwrap_or("") + ); + println!( + "Receipt hash: {}", + receipt["receipt_hash"].as_str().unwrap_or("") + ); + Ok(()) +} diff --git a/2-Search-Space/rust/crates/famm-receipts/src/bin/sidon_famm_map.rs b/2-Search-Space/rust/crates/famm-receipts/src/bin/sidon_famm_map.rs new file mode 100644 index 00000000..def053e1 --- /dev/null +++ b/2-Search-Space/rust/crates/famm-receipts/src/bin/sidon_famm_map.rs @@ -0,0 +1,228 @@ +use anyhow::{Context, Result}; +use clap::Parser; +use famm_receipts::sha256_json; +use serde_json::{json, Value}; +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::path::PathBuf; + +#[derive(Parser)] +struct Args { + #[arg(long)] + config: PathBuf, + #[arg(long)] + out: PathBuf, +} + +fn pair_sums(values: &[i64]) -> Vec { + let mut out = Vec::new(); + for (i, a) in values.iter().enumerate() { + for (offset, b) in values[i..].iter().enumerate() { + let j = i + offset; + out.push(json!({"i": i, "j": j, "a": a, "b": b, "sum": a + b})); + } + } + out +} + +fn find_collisions(pairs: &[Value]) -> Vec { + let mut seen: HashMap = HashMap::new(); + let mut collisions = Vec::new(); + + for pair in pairs { + let sum = pair["sum"].as_i64().unwrap_or_default(); + if let Some(previous) = seen.get(&sum) { + let current_indices = HashSet::from([ + pair["i"].as_u64().unwrap_or_default(), + pair["j"].as_u64().unwrap_or_default(), + ]); + let previous_indices = HashSet::from([ + previous["i"].as_u64().unwrap_or_default(), + previous["j"].as_u64().unwrap_or_default(), + ]); + if current_indices != previous_indices { + collisions.push(json!({ + "sum_address": sum, + "pair_a": { + "i": previous["i"], + "j": previous["j"], + "values": [previous["a"].clone(), previous["b"].clone()] + }, + "pair_b": { + "i": pair["i"], + "j": pair["j"], + "values": [pair["a"].clone(), pair["b"].clone()] + }, + "trivial_collision": false, + "scar": "nontrivial_pair_sum_collision" + })); + } + } else { + seen.insert(sum, pair); + } + } + + collisions +} + +fn candidate_gate(values: &[i64], candidate: i64) -> Value { + let current_sums = pair_sums(values) + .into_iter() + .filter_map(|pair| pair["sum"].as_i64()) + .collect::>(); + + let mut new_sums = values + .iter() + .map(|x| json!({"a": candidate, "b": x, "sum": candidate + x})) + .collect::>(); + new_sums.push(json!({"a": candidate, "b": candidate, "sum": 2 * candidate})); + + let external = new_sums + .iter() + .filter(|pair| { + pair["sum"] + .as_i64() + .is_some_and(|sum| current_sums.contains(&sum)) + }) + .cloned() + .collect::>(); + + let unique = new_sums + .iter() + .filter_map(|pair| pair["sum"].as_i64()) + .collect::>(); + let internal_count = new_sums.len().saturating_sub(unique.len()); + let admissible = external.is_empty() && internal_count == 0; + + json!({ + "candidate": candidate, + "admissible": admissible, + "new_sums": new_sums, + "external_collisions": external, + "internal_duplicate_count": internal_count + }) +} + +fn additive_energy_ordered(values: &[i64]) -> i64 { + let mut counts: HashMap = HashMap::new(); + for a in values { + for b in values { + *counts.entry(a + b).or_default() += 1; + } + } + counts.values().map(|count| count * count).sum() +} + +fn run(config: &Value) -> Result { + let values = config["set"] + .as_array() + .context("config.set must be an array")? + .iter() + .map(|value| value.as_i64().context("set values must be integers")) + .collect::>>()?; + + let pairs = pair_sums(&values); + let collisions = find_collisions(&pairs); + let m = values.len() as i64; + let e_plus = additive_energy_ordered(&values); + let omega = e_plus - (2 * m * m - m); + let is_sidon = collisions.is_empty() && omega == 0; + + let capacity = config.get("capacity_N").and_then(|capacity| { + capacity.as_f64().map(|n| { + let occupied = values.len() as f64; + json!({ + "N": n as i64, + "theodorus_shell_sqrt_N": n.sqrt(), + "occupied": values.len(), + "slack": n.sqrt() - occupied + }) + }) + }); + + let candidate_receipt = config + .get("candidate") + .and_then(Value::as_i64) + .map(|candidate| candidate_gate(&values, candidate)); + + let capacity_pressure = capacity + .as_ref() + .and_then(|c| c["slack"].as_f64()) + .map(|slack| -slack); + + let famm = json!({ + "sidon_collision_count": collisions.len(), + "additive_energy_ordered": e_plus, + "omega_sidon": omega, + "scar_class": if is_sidon { "PASS_ZERO_SCAR" } else { "COLLISION_SCAR" }, + "coarsening_agent": if is_sidon { + Value::Null + } else { + json!({ + "type": "sidon_collision_coarsener", + "action": "downweight_or_merge_collision_basin", + "reason": "nontrivial pair-sum collision or additive energy excess" + }) + }, + "capacity": capacity, + "candidate_gate": candidate_receipt, + "semantic_mass_lanes": { + "collision": collisions.len(), + "additive_energy_excess": omega, + "capacity_pressure": capacity_pressure, + "residual": if is_sidon { 0 } else { collisions.len() as i64 + omega.max(0) } + } + }); + + let mut receipt = json!({ + "receipt_type": "famm_sidon_map_receipt", + "schema_version": "0.1.0", + "set": values, + "is_sidon": is_sidon, + "pair_sums": pairs, + "collisions": collisions, + "famm": famm, + "no_drift_boundary": "This receipt verifies Sidon pair-sum uniqueness and maps failures to FAMM scars. It does not prove maximality or physical realization." + }); + + let hash = sha256_json(&receipt); + receipt["receipt_hash"] = json!(hash); + Ok(receipt) +} + +fn main() -> Result<()> { + let args = Args::parse(); + let config_text = fs::read_to_string(&args.config) + .with_context(|| format!("failed to read {}", args.config.display()))?; + let config: Value = serde_json::from_str(&config_text) + .with_context(|| format!("failed to parse {}", args.config.display()))?; + let receipt = run(&config)?; + + if let Some(parent) = args.out.parent() { + fs::create_dir_all(parent)?; + } + fs::write(&args.out, serde_json::to_string_pretty(&receipt)?)?; + + println!("Wrote {}", args.out.display()); + println!("Sidon: {}", receipt["is_sidon"].as_bool().unwrap_or(false)); + println!( + "Collision count: {}", + receipt["famm"]["sidon_collision_count"] + .as_u64() + .unwrap_or_default() + ); + println!("Omega Sidon: {}", receipt["famm"]["omega_sidon"]); + if !receipt["famm"]["candidate_gate"].is_null() { + println!( + "Candidate admissible: {}", + receipt["famm"]["candidate_gate"]["admissible"] + .as_bool() + .unwrap_or(false) + ); + } + println!( + "Receipt hash: {}", + receipt["receipt_hash"].as_str().unwrap_or("") + ); + Ok(()) +} diff --git a/2-Search-Space/rust/crates/famm-receipts/src/lib.rs b/2-Search-Space/rust/crates/famm-receipts/src/lib.rs new file mode 100644 index 00000000..01c3b007 --- /dev/null +++ b/2-Search-Space/rust/crates/famm-receipts/src/lib.rs @@ -0,0 +1,44 @@ +use serde_json::Value; +use sha2::{Digest, Sha256}; + +pub fn canonical_json(value: &Value) -> String { + match value { + Value::Null => "null".to_string(), + Value::Bool(v) => v.to_string(), + Value::Number(v) => v.to_string(), + Value::String(v) => serde_json::to_string(v).expect("string serialization cannot fail"), + Value::Array(values) => { + let body = values + .iter() + .map(canonical_json) + .collect::>() + .join(","); + format!("[{body}]") + } + Value::Object(map) => { + let mut keys = map.keys().collect::>(); + keys.sort(); + let body = keys + .into_iter() + .map(|key| { + let key_json = + serde_json::to_string(key).expect("key serialization cannot fail"); + let value_json = canonical_json(&map[key]); + format!("{key_json}:{value_json}") + }) + .collect::>() + .join(","); + format!("{{{body}}}") + } + } +} + +pub fn sha256_json(value: &Value) -> String { + let payload = canonical_json(value); + let digest = Sha256::digest(payload.as_bytes()); + format!("{digest:x}") +} + +pub fn clamp01(x: f64) -> f64 { + x.clamp(0.0, 1.0) +}