spec 01 1.4.7.6: the class v5 constants table (one row per igneum-pow pub const, for the spec-constants check); igneum-pow: the listed-programs (c''') reading as an ignored test (IGNEUM_V5_PROGRAMS file: epoch, era, attempt per line)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-07 22:21:24 +00:00
parent c17ce3b287
commit 5ae7e2c5a5
2 changed files with 77 additions and 0 deletions

View file

@ -232,6 +232,21 @@ Class v5 is a program-class step like class v4's (section 2's class signal): the
The acceptance vectors of (c'''): seed 100767 of the f8 label space (epoch bytes the words of `igneum-attack-f8/program/100767`, era bytes of `igneum-attack-f8/era/100767`) is accepted under class v4 at attempt 2 (`9d68e6286fc817d4`, site 6 at 0.9919) and refused under class v5 at attempt 2 by (c''') naming site 6 at 0.991; the class v5 draw lands on attempt 4 (`734fbb8e3e4cd20f`); the genesis draws of both classes read 0.9990 at their minimum site. The day vector of AP-F4-1: chain day 29,337 under class v4 draws a mixer block of cost 203 and class v5 redraws it. The last-resort vector: seed adv3/steer/2 (`igneum-adv-accept-3/steer/2`, Devnet 3's genesis as the era) at attempt 256 fails part (a) at instruction 47 reading r3 under the class v4 rewrite; class v5's last resort passes at attempt 256 (`9b29c9481f6941d4`). The crate's tests hold every row (`tests/packs.rs`, `accept::tests`, `memhard::tests`, `generator::tests`).
#### 1.4.7.6 Constants
One row per Rust `pub const` of igneum-pow that class v5 adds; the gate's spec-constants check reads the value column against the crate. `CLASS_SIGNAL_V5 = 6` and `CLASS_SIGNAL_WINDOWS = 7` are the fork's (`consensus/core/src/igneum.rs`) and are named in 1.4.7.4; class v5's attempt cap is class v4's `MAX_ATTEMPTS_V4 = 256` (section 1.4.6).
| Constant | Value | Where |
|---|---|---|
| `MIN_DISTINCT_RATIO_V5` | 0.995 | `igneum-pow/src/accept.rs`, part (c''') |
| `MIXER_COST_REJECT_MAX` | 205 | `igneum-pow/src/memhard.rs`, AP-F4-1 |
| `MIXER_NAF_WORD_MIN` | 4 | `igneum-pow/src/memhard.rs`, AP-F4-1 (a multiplier with `w32` under this, a two-adder chain, rejects) |
| `MIXER_REDRAW_CAP` | 64 | `igneum-pow/src/memhard.rs` |
| `SHADOW_REMOVABLE_MAX_PERMILLE` | 30 | `igneum-pow/src/generator.rs`, AP-F1-1 |
| `SHADOW_REDRAW_CAP` | 64 | `igneum-pow/src/generator.rs` |
| `LAST_RESORT_SCAN` | 256 | `igneum-pow/src/generator.rs`, the verified last resort |
| `GENERATOR_VERSION_V5` | 5 | `igneum-pow/src/generator.rs` |
## 1.5 Fixed memory footprint
Implemented for the prototype size; Designed for genesis.

View file

@ -883,6 +883,68 @@ mod tests {
assert_eq!(v5_under, 0);
}
/// The (c''') reading on a listed set of chain-shaped programs (run by hand on a box through the lease): the file
/// `IGNEUM_V5_PROGRAMS` holds one program per line, `<epoch hex or label> <era hex or label> <attempt> [tag...]`
/// (a hex field of 64 characters is the 32 bytes; anything else is a label whose `seed_words_from_bytes` words are
/// the bytes, as the f8 and adv label spaces derive theirs). Per line: the class v4 program at that attempt (its id,
/// minimum site and ratio at the 2^20 sample), the class v5 verdict at the same attempt, and the class v5 draw's
/// attempt. The coordinator's question of 7 October 2026, 23:3x UK: whether the drawn-era programs adv-cache-2 read
/// as biased (R from 3 to 22) sit under the 0.995 floor.
#[test]
#[ignore]
fn v5_floor_on_listed_programs() {
use crate::generator::{V5_CLASS, V3_ALLOWED};
use crate::seed::seed_words_from_bytes;
let path = std::env::var("IGNEUM_V5_PROGRAMS").expect("IGNEUM_V5_PROGRAMS=<file>");
let text = std::fs::read_to_string(&path).expect("the programs file");
let bytes_of = |f: &str| -> Vec<u8> {
if f.len() == 64 && f.chars().all(|c| c.is_ascii_hexdigit()) {
crate::bind::unhex(f).unwrap()
} else {
seed_words_from_bytes(f.as_bytes()).iter().flat_map(|x| x.to_le_bytes()).collect()
}
};
let mut refused = 0;
let mut rows = 0;
for line in text.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let f: Vec<&str> = line.split_whitespace().collect();
if f.len() < 3 {
println!("skip (needs epoch era attempt): {line}");
continue;
}
let (epoch, era, attempt) = (bytes_of(f[0]), bytes_of(f[1]), f[2].parse::<u32>().expect("attempt"));
let tag = f[3..].join(" ");
let label = format!("igneum-epoch/{}", epoch.iter().map(|b| format!("{b:02x}")).collect::<String>());
let v4 = candidate_class(&label, &epoch, attempt, LoadClass::era(V4_CLASS, &era, &V3_ALLOWED));
let st = site_index_stats(&v4, ACCEPT_UNITS_DISTINCT_V4).unwrap();
let (min, site) = distinct_ratio_on(&v4, &st, ACCEPT_UNITS_DISTINCT_V4, 0.0).unwrap();
let v4_verdict = check(&v4).is_ok();
let v5 = candidate_class(&label, &epoch, attempt, LoadClass::era(V5_CLASS, &era, &V3_ALLOWED));
let v5_verdict = check(&v5);
let drawn = f8_draw(&epoch, &era, V5_CLASS);
let era_params = v4.class.era.as_ref().map(|e| e.stride_rot).unwrap_or(0);
rows += 1;
if v5_verdict.is_err() {
refused += 1;
}
println!(
"listed: id {:016x} attempt {attempt} R {era_params} | v4 {} min site {site} ratio {min:.4} (most read {:#x} x{}) | v5 at this attempt {} | v5 draw attempt {} id {:016x} | {tag}",
crate::generator::program_id(crate::generator::GENERATOR_VERSION_V4, &v4.seed, attempt),
if v4_verdict { "accepted" } else { "REJECTED" },
st[site].top_index,
st[site].top_count,
match &v5_verdict { Ok(_) => "accepted".to_string(), Err(r) => format!("REFUSED {r}") },
drawn.attempt,
drawn.program_id()
);
}
println!("listed: {refused} of {rows} refused under class v5 at the listed attempt");
}
#[test]
fn distinct_bound_scales_with_the_load_count() {
assert_eq!(min_distinct_sum(128), MIN_DISTINCT_SUM);