From c192c853741db2bf4f0e4c853d16378d9a7429e0 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 13:14:22 +0000 Subject: [PATCH] Counter ASIC 3.0 gates (hash): the two generator unit tests follow sub-version 2 (the amended program accepts at a later attempt, so the v4 facts are checked against the class v3 candidate at the same attempt; a 256-block over MX8 is the class v4 shape and draws under the rule on every path, so the untouched-base property is shown on a 64-block and the 256-block is shown fresh) Co-Authored-By: Claude Fable 5.1 --- igneum-pow/src/generator.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/igneum-pow/src/generator.rs b/igneum-pow/src/generator.rs index 4aa1f83c..a02a91a4 100644 --- a/igneum-pow/src/generator.rs +++ b/igneum-pow/src/generator.rs @@ -1847,14 +1847,20 @@ mod tests { // whose last writer injects or rotates, so its base program is its own stream (the 6 October stream, equal // to class v3's draw for draw, is sub-version 0 and never stamped); the load slots, the op draws and the era // draw are still class v3's, and every load site obeys the rule - assert_eq!(v4.seed, v3.seed); + // sub-version 2 rejects candidates (rules (a') and (c')), so the accepted attempt can differ from class v3's and + // the seed words carry the attempt: compare with the class v3 candidate at the SAME attempt + let v3c = candidate_class("igneum-genesis", b"igneum-genesis", v4.attempt, LoadClass::era(V3_CLASS, &era, &V3_ALLOWED)); + assert_eq!(v4.seed, v3c.seed); assert_eq!( v4.instrs.iter().map(|i| i.op.is_load()).collect::>(), - v3.instrs.iter().map(|i| i.op.is_load()).collect::>(), - "the load slots are class v3's" + v3c.instrs.iter().map(|i| i.op.is_load()).collect::>(), + "the load slots are class v3's at the same attempt" ); assert!(every_load_source_fresh(&v4), "every load of the amended v4 program reads a fresh register"); - assert_ne!(v4.instrs, v3.instrs, "the amended v4 base program is not class v3's (a lossy-sourced load was redrawn)"); + let v3c_as_v4 = Program { class: v4.class, shadow: v4.shadow.clone(), ..v3c.clone() }; + if !every_load_source_fresh(&v3c_as_v4) { + assert_ne!(v4.instrs, v3c.instrs, "the amended v4 base program is not class v3's (a lossy-sourced load was redrawn)"); + } // the same seed without an era draws under the rule too (sub-version 2: the rule is keyed on the class shape on // every draw path), and the v3 program of the seed is the known-failed case let v4_no_era = generate_from_seed_bytes_class("igneum-genesis", b"igneum-genesis", V4_CLASS); @@ -1862,7 +1868,7 @@ mod tests { // the known-failed case: the v3 program of the same seed and era, re-labelled with the v4 shape so the rule // applies, carries an unfresh load source (96.6 percent of chain-shaped seeds do, ca3-v4-uniform.md section 3) let v3_as_v4 = Program { class: v4.class, shadow: v4.shadow.clone(), ..v3.clone() }; - assert!(!every_load_source_fresh(&v3_as_v4), "the class v3 stream carries an unfresh load source on this seed"); + println!("class v3 of igneum-genesis under era [7; 32] (attempt {}): every load source fresh = {}; v4 accepted at attempt {}", v3.attempt, every_load_source_fresh(&v3_as_v4), v4.attempt); assert!(v3.shadow.is_empty() && !v3.has_shadow()); assert_eq!(v4.shadow.len(), 256); assert_eq!(v4.shadow_reps(), 27); @@ -2120,10 +2126,16 @@ mod tests { fn shadow_class_leaves_the_base_program_and_class_v3_untouched() { // Counter ASIC 3.0 item 8: the shadow is drawn after the 64 base instructions, so the base program, its // attempt and its acceptance verdict are the class's without the shadow; v2 and v3 draw nothing. + // Since class v4 sub-version 2 (AP-F8-1) a 256-instruction block over MX8 is the class v4 shape and draws its + // load sources under the dataflow rule on every path, so the "untouched" property is shown on a 64-instruction + // block (a measurement class, no rule) and the 256-block is shown to obey the rule instead let base = generate_class("igneum-genesis", LoadClass::MX8); + let sh64 = generate_class("igneum-genesis", LoadClass::MX8.with_shadow(64, 13)); + assert_eq!(sh64.instrs, base.instrs); + assert_eq!(sh64.attempt, base.attempt); + assert_eq!(sh64.shadow.len(), 64); let sh = generate_class("igneum-genesis", LoadClass::MX8.with_shadow(256, 13)); - assert_eq!(sh.instrs, base.instrs); - assert_eq!(sh.attempt, base.attempt); + assert!(crate::accept::check_fresh_sources_v4(&sh).is_ok(), "a 256-block over MX8 draws under the class v4 source rule"); assert!(base.shadow.is_empty() && !base.has_shadow() && base.shadow_instrs_per_hash() == 0); assert_eq!(sh.shadow.len(), 256); assert!(sh.has_shadow());