Counter ASIC 4.0 research: the per-load 16 x 27 construction is dead as a chain class (the acceptance rule in execution order accepts 1.4 percent of its candidates)

accept.rs: the per-load class's value-level test (the adv-cache-2 requirement): the one-count of every index bit per load site over the 64 units' 16,384 addresses, BiasedIndexBit outside the 6-sigma band (384 of 8,192); generator: a sub-block writer of the next load's source is never a product (mad joins mul, mulhi, or). The record (tests/ca4_trace.rs, igneum-build-2, 22:44 to 22:52 UTC): over 64 seeds 22 of 1,621 candidates accepted (1.4 percent), 42 of 64 seeds exhaust the chain's 32 attempts; the first failing test: biased index bit 775, duplicate lanes 643, the base rule 110, (b) 43, (a) 28; the genesis seed 0 of 32; candidate 0 of the class carries index bit 0 at 40 of 1,024 at site 0 (z 29.5, sub-block writer rotl of a mad). The class v4 shape across 16 drawn eras: 0 duplicate pairs, with the biased product bit at address bit R exactly in 14 of 17 eras on this pre-amendment generator (the adv-cache-2 class, replicated). The tests record these as reports and bounds; the construction stays in the crate behind the pack as the measured dead end, never a chain class.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-07 22:53:16 +00:00
parent d267043677
commit 0449221245
3 changed files with 169 additions and 63 deletions

View file

@ -64,6 +64,9 @@ pub enum Reject {
/// (c, the per-load shadow class only; Counter ASIC 4.0 research, experimental): the load at `instr` in
/// `iteration` read one address in `dups` pairs of lanes of `unit` (the class v4 shape is not held to this).
DuplicateLanes { iteration: u8, instr: u8, unit: u8, dups: u8 },
/// (c, the per-load shadow class only; Counter ASIC 4.0 research, the adv-cache-2 requirement): index bit `bit` at
/// load site `site` was set in `ones` of the 16,384 addresses of the 64 units, outside the 6-sigma band.
BiasedIndexBit { site: u8, bit: u8, ones: u32 },
}
impl std::fmt::Display for Reject {
@ -74,6 +77,9 @@ impl std::fmt::Display for Reject {
}
Reject::NoInjectingWrite { reg } => write!(f, "(b) r{reg} has no add, sub, xor, mad, shfl or load write"),
Reject::ConstantBit { reg, bits } => write!(f, "(c) r{reg} has {bits} nonce-independent bits"),
Reject::BiasedIndexBit { site, bit, ones } => {
write!(f, "(c, per-load shadow) index bit {bit} at load site {site} set in {ones} of 16,384 addresses")
}
Reject::DuplicateLanes { iteration, instr, unit, dups } => {
write!(f, "(c, per-load shadow) load at iteration {iteration} instruction {instr} reads a duplicate address in {dups} lanes of unit {unit}")
}
@ -178,6 +184,8 @@ struct Acc {
saturated: u32,
bit_ones: [u32; 64],
distinct_sum: u64,
/// Counter ASIC 4.0 research (the per-load class only): one-count of every index bit per load site over the units.
site_bit_ones: Vec<[u32; 32]>,
}
/// One ALU instruction of a shadow sub-block on the register file (the same arithmetic as the arms of `run_unit`;
@ -390,6 +398,12 @@ fn run_unit(p: &Program, unit: usize, base: u32, acc: &mut Acc, lane_addrs: &mut
if dups > 0 {
return Err(Reject::DuplicateLanes { iteration: it as u8, instr: k as u8, unit: unit as u8, dups: dups as u8 });
}
let site = load_j % acc.site_bit_ones.len();
for &x in &idx {
for b in 0..32 {
acc.site_bit_ones[site][b] += (x >> b) & 1;
}
}
}
for lane in 0..LANES {
if width == 1 {
@ -472,11 +486,29 @@ fn run_unit(p: &Program, unit: usize, base: u32, acc: &mut Acc, lane_addrs: &mut
/// Part (c).
pub fn check_dynamic(p: &Program) -> Result<AcceptReport, Reject> {
let loads = p.loads_per_hash();
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0 };
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0, site_bit_ones: Vec::new() };
if p.shadow_per_load() {
acc.site_bit_ones = vec![[0u32; 32]; p.instrs.iter().filter(|i| i.op.is_load()).count().max(1)];
}
let mut lane_addrs = vec![0u32; LANES * loads];
for (unit, &base) in accept_base_nonces(&p.seed).iter().enumerate() {
run_unit(p, unit, base, &mut acc, &mut lane_addrs)?;
}
if p.shadow_per_load() {
// the value-level test (the adv-cache-2 requirement, 7 October 2026): an index bit whose one-count over the
// 64 units' 16,384 addresses at one site sits outside 6 sigma of n / 2 (n / 2 = 8,192, sigma 64, band 384) is a
// biased address bit (a product's low bit placed by the stride rotation reads 1/4 or 3/4: 4,096 off, 64 sigma)
let n = (ACCEPT_UNITS * ITERATIONS * LANES) as u32;
let band = 6 * ((n as f64) / 4.0).sqrt() as u32;
for (site, bits) in acc.site_bit_ones.iter().enumerate() {
for bit in 0..ACCEPT_DATASET_LOG2 as usize {
let ones = bits[bit];
if ones.abs_diff(n / 2) > band {
return Err(Reject::BiasedIndexBit { site: site as u8, bit: bit as u8, ones });
}
}
}
}
for reg in 0..8 {
let bits = (acc.and_acc[reg] | !acc.or_acc[reg]).count_ones();
if bits != 0 {
@ -539,7 +571,7 @@ mod tests {
let ds = DatasetSource::from_key(p.seed, DatasetMode::ClosedForm, ACCEPT_DATASET_LOG2);
let bases = accept_base_nonces(&p.seed);
let loads = p.loads_per_hash();
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0 };
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0, site_bit_ones: Vec::new() };
let mut la = vec![0u32; LANES * loads];
let mut ones = [0u32; 64];
for (u, &b) in bases.iter().enumerate() {
@ -562,7 +594,7 @@ mod tests {
let p = candidate(&s, s.as_bytes(), 0);
let ds = DatasetSource::from_key(p.seed, DatasetMode::ClosedForm, ACCEPT_DATASET_LOG2);
let bases = accept_base_nonces(&p.seed);
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0 };
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0, site_bit_ones: Vec::new() };
let mut la = vec![0u32; LANES * p.loads_per_hash()];
let mut ones = [0u32; 64];
let mut any = false;
@ -605,7 +637,7 @@ mod tests {
let p = generate_class("igneum-genesis", LoadClass::hot(96, 4));
let words = p.hot_words();
let loads = p.loads_per_hash();
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0 };
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0, site_bit_ones: Vec::new() };
let mut la = vec![0u32; LANES * loads];
let mut buckets = [0u64; 16];
let mut hot_count = 0u64;

View file

@ -1424,13 +1424,13 @@ pub fn candidate_from_words_class(
let dst = rng.below(8);
if sh.per_load && sub_len > 0 && !load_srcs.is_empty() {
// the rule: a sub-block instruction that writes the next load's source register is drawn from the
// bijective families only (add, sub, xor, mad, shfl, rotl, rotr); mul, mulhi and or are redrawn from
// non-product injecting families only (add, sub, xor, shfl); mul, mulhi, or and mad are redrawn (the biased-product-bit class of 22:3x UTC) from
// the injecting table (sub-version 3's source rule applied to the order this class executes)
let j = k / sub_len;
let next_src = load_srcs[(j + 1) % load_srcs.len()];
if dst as usize == next_src && matches!(op, Op::Mul | Op::MulHi | Op::Or) {
let inj: [(Op, u64); 5] = [(Op::Add, 12), (Op::Sub, 6), (Op::Xor, 10), (Op::Mad, 8), (Op::Shfl, 8)];
let mut r2 = rng.below(44);
if dst as usize == next_src && matches!(op, Op::Mul | Op::MulHi | Op::Or | Op::Mad) {
let inj: [(Op, u64); 4] = [(Op::Add, 12), (Op::Sub, 6), (Op::Xor, 10), (Op::Shfl, 8)];
let mut r2 = rng.below(36);
for &(o, w) in &inj {
if r2 < w {
op = o;
@ -2323,7 +2323,11 @@ mod ca4_tests {
assert_eq!(V4_CLASS.name(), "mx8+sh256x27", "the class v4 name is unchanged");
let seed = b"igneum-genesis";
let p4 = generate_from_seed_bytes_class("t", seed, v4);
let pp = generate_from_seed_bytes_class("t", seed, pl);
// the per-load 16 x 27 construction is refused by the acceptance rule on every attempt once the rule steps the
// sub-blocks in execution order (22:4x UTC, tests/ca4_trace.rs): its candidates are read, never accepted
let pl_attempts = attempts_class("t", seed, pl);
assert!(pl_attempts.len() > 8, "the per-load class accepts 1.4 percent of candidates (22:4x UTC); seed t took {} attempts", pl_attempts.len());
let pp = pl_attempts[0].0.clone();
let pm = generate_from_seed_bytes_class("t", seed, mm);
let pb = generate_from_seed_bytes_class("t", seed, both);
// the per-load class takes the dynamic acceptance test in its own execution order (accept.rs DuplicateLanes),
@ -2331,8 +2335,6 @@ mod ca4_tests {
// when the attempt is the same the base program is the class v4 shape's draw for draw
if pp.attempt == p4.attempt {
assert_eq!(p4.instrs, pp.instrs, "the base program is the class's without the shadow, draw for draw");
} else {
assert!(pp.attempt > p4.attempt, "a per-load candidate is only ever rejected more, never less");
}
assert_eq!(p4.shadow.len(), pp.shadow.len(), "the per-load shadow holds a block of the same size");
assert!(p4.tiles.is_empty() && pp.tiles.is_empty());

View file

@ -12,7 +12,15 @@ fn per_load_shadow_duplicate_reads_are_counted_per_site() {
let seed = igneum_pow::seed::seed_words_from_bytes(b"igneum-genesis");
for name in ["mx8+sh256x27", "mx8+shl256x27"] {
let class = LoadClass::parse(name).unwrap();
let p = generate_from_seed_bytes_class("igneum-genesis", b"igneum-genesis", class);
// the per-load class is refused by the acceptance rule on every attempt (22:4x UTC): its candidate 0 is read here
// as the known-failed record (the first export's program), the class v4 shape through the accepted program
let p = if name == "mx8+shl256x27" {
let v = igneum_pow::generator::attempts_class("igneum-genesis", b"igneum-genesis", class);
println!("CA4VERDICT igneum-genesis per-load 16 x 27: {} candidates, accepted {}", v.len(), v.iter().filter(|(_, r)| r.is_ok()).count());
v.into_iter().next().unwrap().0
} else {
generate_from_seed_bytes_class("igneum-genesis", b"igneum-genesis", class)
};
let mut total_distinct = 0usize;
let mut per_site = vec![0usize; 16];
let mut dup_pairs_same_iter = 0usize;
@ -48,8 +56,10 @@ fn per_load_shadow_duplicate_reads_are_counted_per_site() {
// the known-failed record (the first export, 22:1x UTC): 10,728 distinct of 12,288 over three units and
// 1,482 same-iteration duplicate lanes at sites 8, 10 and 15, whose sub-block last writer of the load's
// source was `mul`; after the 22:3x UTC rule the class must read 0 duplicates like the class v4 shape
assert!(dup_pairs_same_iter <= 2, "per-load duplicate reads: {per_site:?}");
assert!(total_distinct >= 12_280, "{total_distinct}");
// the known-failed record (the first export, id 854050a4293f0615: 10,728 distinct of 12,288, 1,482 duplicate
// lanes) was drawn before the static redraw layer; today's candidate 0 is another program, so its figures are
// printed, not asserted (the file carries the record; the pack proto-cuda/packs-ca4/mx8_shl256x27 is the program)
let _ = (dup_pairs_same_iter, total_distinct);
}
println!(
"CA4TRACE class {name}: distinct items per unit (3 units of 4,096 reads) {total_distinct} of 12,288; within-warp duplicate lanes per site over 3 units x 8 iterations {:?}; same-iteration duplicate lanes {dup_pairs_same_iter}; sub-block last writers of load sources {:?}",
@ -59,59 +69,35 @@ fn per_load_shadow_duplicate_reads_are_counted_per_site() {
}
#[test]
fn per_load_shadow_census_64_seeds_has_no_duplicate_reads() {
let ds = DatasetSource::new("2026-10-03", DatasetMode::ClosedForm, 24);
fn per_load_shadow_census_64_seeds_is_refused_on_every_attempt() {
// the verdict of 22:4x UTC: with the acceptance rule stepping the per-load sub-blocks in the order the class
// executes (duplicate lanes at a load row, biased index bits at a site over the 64 units), no candidate of the
// 16 x 27 construction passes; the histogram of first failing tests is the record
use igneum_pow::generator::attempts_class;
let class = LoadClass::parse("mx8+shl256x27").unwrap();
let mut worst = (0usize, String::new());
let mut redrawn_total = 0usize;
let mut failures: Vec<String> = Vec::new();
let mut accepted = 0usize;
let mut attempts_total = 0usize;
let mut hist: std::collections::BTreeMap<String, usize> = std::collections::BTreeMap::new();
for n in 0..64u32 {
let label = format!("ca4-census/{n}");
let p = generate_from_seed_bytes_class(&label, label.as_bytes(), class);
let v4 = generate_from_seed_bytes_class(&label, label.as_bytes(), LoadClass::parse("mx8+sh256x27").unwrap());
redrawn_total += p.shadow.iter().zip(v4.shadow.iter()).filter(|(x, y)| x != y).count();
let seed = igneum_pow::seed::seed_words_from_bytes(label.as_bytes());
let mut dups = 0usize;
for base in [0u32, 1 << 20] {
for row in trace_load_indices(&p, &seed, base, &ds) {
let s: HashSet<u32> = row.iter().copied().collect();
dups += 32 - s.len();
}
}
if dups > worst.0 {
worst = (dups, label.clone());
}
if dups > 0 {
// the diagnostic for a seed the rule does not cover: per-site duplicates and the sub-block writers of each
// load's source (every writer, not only the last)
let loads: Vec<_> = p.instrs.iter().filter(|i| i.op.is_load()).collect();
let mut per_site = vec![0usize; 16];
for base in [0u32, 1 << 20] {
for (k, row) in trace_load_indices(&p, &seed, base, &ds).iter().enumerate() {
let s: HashSet<u32> = row.iter().copied().collect();
per_site[k % 16] += 32 - s.len();
let v = attempts_class(&label, label.as_bytes(), class);
attempts_total += v.len();
for (_, r) in &v {
match r {
Ok(()) => accepted += 1,
Err(e) => {
let s = e.to_string();
let key = if s.contains("duplicate address") { "(c) per-load duplicate lanes" } else if s.contains("index bit") { "(c) per-load biased index bit" } else if s.starts_with("(a)") { "(a) stale source" } else if s.starts_with("(b)") { "(b) no injecting write" } else { "(c) base rule" };
*hist.entry(key.to_string()).or_insert(0) += 1;
}
}
for (j, ld) in loads.iter().enumerate() {
if per_site[j] == 0 {
continue;
}
let prev = if j == 0 { 15 } else { j - 1 };
let sub = p.shadow_sub_block(prev);
let ws: Vec<String> = sub.iter().filter(|i| i.dst == ld.src).map(|i| format!("{}(src r{})", i.op.name(), i.src)).collect();
let base_writers: Vec<String> = p.instrs.iter().take_while(|i| !(std::ptr::eq(*i, *ld))).filter(|i| i.dst == ld.src).map(|i| i.op.name().to_string()).collect();
println!("CA4FAIL seed {label} site {j} dups {} load src r{} sub-block writers of r{}: {:?}; base writers before the load: {:?}; distinct src values at the load (unit 0): {}", per_site[j], ld.src, ld.src, ws, base_writers.last(), {
let rows = trace_load_indices(&p, &seed, 0, &ds); let s: HashSet<u32> = rows[j].iter().copied().collect(); s.len() });
}
failures.push(label.clone());
}
}
println!("CA4CENSUS 64 seeds x 2 units of the per-load class: 0 within-warp duplicate reads on every seed; instructions redrawn by the rule {redrawn_total} of {} ({:.2} percent); worst {:?}", 64 * 256, redrawn_total as f64 / (64.0 * 256.0) * 100.0, worst);
// the chance floor: two of 32 lanes landing on one index in a 2^24-word dataset is 32 x 31 / 2 / 2^24, about
// 3e-5 per row, about 0.5 pairs over this census's 16,384 rows (the class v4 shape itself reads 2 of 12,288 in
// the trace above); the fault class read 1,482 pairs over 384 rows. A seed over 4 pairs is a fault.
let total: usize = failures.len();
assert!(worst.0 <= 4 && total <= 3, "seeds with duplicate reads beyond the chance floor: {failures:?} worst {worst:?}");
let seeds_without = 64 - accepted;
println!("CA4CENSUS per-load 16 x 27 over 64 seeds: {accepted} accepted of {attempts_total} candidates ({:.1} percent); {seeds_without} of 64 seeds exhaust the chain's 32 attempts; first failing test {hist:?}", accepted as f64 / attempts_total as f64 * 100.0);
// the record of 22:4x UTC: 22 of 1,621 (1.4 percent), 42 seeds without a program; a construction that accepts
// under 5 percent of its candidates is dead as a chain class at the 32-attempt cap
assert!((accepted as f64) < 0.05 * attempts_total as f64, "the acceptance rate moved: {accepted} of {attempts_total}");
}
#[test]
@ -121,14 +107,15 @@ fn per_load_shadow_census_over_16_drawn_eras_splits_by_stride_rotation() {
// R 3 to 22 keeps them in), not the devnet era alone
use igneum_pow::generator::{generate_era, EraParams, V3_ALLOWED};
let ds = DatasetSource::new("2026-10-03", DatasetMode::ClosedForm, 24);
let class = LoadClass::parse("mx8+shl256x27").unwrap();
let mut low = (0usize, 0usize, 0usize); // eras, rows, duplicate pairs with R under 28
let mut high = (0usize, 0usize, 0usize);
let mut lines = Vec::new();
for n in 0..16u32 {
let label = format!("igneum-era-test/{n}");
let eb = EraParams::test_era_bytes(&label);
let p = generate_era("igneum-genesis", b"igneum-genesis", class, &eb, &V3_ALLOWED);
// the per-load class is refused on every attempt (22:4x UTC), so generate_era would panic: the era rows below
// read the class v4 shape as the control of the duplicate-lane statistic across the drawn eras
let p = generate_era("igneum-genesis", b"igneum-genesis", LoadClass::parse("mx8+sh256x27").unwrap(), &eb, &V3_ALLOWED);
let era = p.class.era.expect("an era class");
let seed = igneum_pow::seed::seed_words_from_bytes(b"igneum-genesis");
let mut dups = 0usize;
@ -146,6 +133,91 @@ fn per_load_shadow_census_over_16_drawn_eras_splits_by_stride_rotation() {
bucket.2 += dups;
lines.push(format!("era {n} R={} attempt {} dups {dups}", era.stride_rot, p.attempt));
}
println!("CA4ERA per-load class over 16 drawn eras: R under 28: {} eras, {} rows, {} duplicate pairs; R 28 and up: {} eras, {} rows, {} duplicate pairs; per era {:?}", low.0, low.1, low.2, high.0, high.1, high.2, lines);
println!("CA4ERA class v4 shape (the control; the per-load class is refused on every attempt) over 16 drawn eras: R under 28: {} eras, {} rows, {} duplicate pairs; R 28 and up: {} eras, {} rows, {} duplicate pairs; per era {:?}", low.0, low.1, low.2, high.0, high.1, high.2, lines);
assert!(low.2 + high.2 <= 4, "duplicate reads beyond the chance floor across eras");
}
/// The value-level test 20.2b names: for every load site, the one-count of each index bit over the units' lanes and
/// iterations; a bit outside the binomial band (mean n/2, tolerance 5 sigma) at any site is a biased address bit. Reads
/// the class v4 shape and the per-load class over the devnet-style seed and 16 drawn eras, split by the stride rotation.
#[test]
fn index_bit_bias_per_site_across_eras() {
use igneum_pow::generator::{generate_era, EraParams, V3_ALLOWED};
let ds = DatasetSource::new("2026-10-03", DatasetMode::ClosedForm, 24);
let seed = igneum_pow::seed::seed_words_from_bytes(b"igneum-genesis");
for name in ["mx8+sh256x27", "mx8+shl256x27"] {
let class = LoadClass::parse(name).unwrap();
let mut report = Vec::new();
let mut flagged: Vec<String> = Vec::new();
for n in 0..17u32 {
let (p, r_label) = if n == 16 {
if name == "mx8+shl256x27" {
// candidate 0 of the refused per-load class (the known-failed record)
(igneum_pow::generator::attempts_class("igneum-genesis", b"igneum-genesis", class).into_iter().next().unwrap().0, "none".to_string())
} else {
(generate_from_seed_bytes_class("igneum-genesis", b"igneum-genesis", class), "none".to_string())
}
} else {
if name == "mx8+shl256x27" {
continue; // generate_era has no candidate path and the class is refused; the bare-class row stands
}
let eb = EraParams::test_era_bytes(&format!("igneum-era-test/{n}"));
let p = generate_era("igneum-genesis", b"igneum-genesis", class, &eb, &V3_ALLOWED);
let r = p.class.era.unwrap().stride_rot;
(p, r.to_string())
};
// ones[site][bit] over 4 units x 8 iterations x 32 lanes = 1,024 samples per site
let mut ones = vec![[0u32; 24]; 16];
let mut samples = 0u32;
for base in [0u32, 1 << 20, 7 << 20, 0x0123_4560] {
for (k, row) in trace_load_indices(&p, &seed, base, &ds).iter().enumerate() {
for &x in row {
for b in 0..24 {
ones[k % 16][b] += (x >> b) & 1;
}
}
}
samples += 8 * 32;
}
let mean = samples as f64 / 2.0;
let sigma = (samples as f64 / 4.0).sqrt();
let mut worst = (0.0f64, 0usize, 0usize);
for site in 0..16 {
for b in 0..24 {
let z = (ones[site][b] as f64 - mean).abs() / sigma;
if z > worst.0 {
worst = (z, site, b);
}
}
}
let loads: Vec<_> = p.instrs.iter().filter(|i| i.op.is_load()).collect();
let ld = loads[worst.1];
let writer = p.instrs.iter().take_while(|i| !std::ptr::eq(*i, ld)).filter(|i| i.dst == ld.src).last().map(|i| i.op.name()).unwrap_or("none");
let sub_writer = if p.shadow_per_load() {
let prev = if worst.1 == 0 { 15 } else { worst.1 - 1 };
p.shadow_sub_block(prev).iter().filter(|i| i.dst == ld.src).last().map(|i| i.op.name()).unwrap_or("none")
} else { "n/a" };
report.push(format!("R={r_label} worst z {:.1} at site {} bit {} (ones {} of {samples}; base writer {writer}, sub-block writer {sub_writer})", worst.0, worst.1, worst.2, ones[worst.1][worst.2]));
if worst.0 >= 5.0 {
flagged.push(report.last().unwrap().clone());
}
}
println!("CA4BIAS class {name}: index bit one-counts over 1,024 samples per site, 16 sites x 24 bits, 16 drawn eras plus the bare class: {:?}; flagged (z at or over 5) {}", report, flagged.len());
// a report, not a gate: on this generator (master, before the sub-version 3 source rule) the class v4 shape itself
// carries the biased product bit at address bit R (adv-cache-2, 7 October 2026); the per-load class is read beside it
if name == "mx8+shl256x27" {
assert!(!flagged.is_empty(), "candidate 0 of the per-load class carries the biased product bit (the record)");
}
}
}
#[test]
fn per_load_attempt_verdicts_on_the_test_seed() {
use igneum_pow::generator::attempts_class;
let class = LoadClass::parse("mx8+shl256x27").unwrap();
for seed in ["t", "igneum-genesis", "ca4-census/0", "ca4-census/1"] {
let v = attempts_class(seed, seed.as_bytes(), class);
let verdicts: Vec<String> = v.iter().map(|(p, r)| format!("a{} {}", p.attempt, match r { Ok(()) => "OK".to_string(), Err(e) => e.to_string() })).collect();
println!("CA4ATTEMPTS seed {seed}: {} attempts; {:?}", v.len(), verdicts);
}
}