diff --git a/app/igneum-app/src/provedefault.rs b/app/igneum-app/src/provedefault.rs index 6aebd90d..2516fdae 100644 --- a/app/igneum-app/src/provedefault.rs +++ b/app/igneum-app/src/provedefault.rs @@ -26,6 +26,24 @@ pub const MIN_VRAM_MB_PROVE_ONLY: u64 = 23_552; /// miner), the devnet's shard until its fee switch at DAA 210,000; `nvidia-smi` reports 32,607 for the RTX 5090. pub const VRAM_MB_PROTOTYPE_SHARD: u64 = 31_000; +/// Main's rule (7 October 2026, the fleet's prover roll): a 10 GB card never completes the compressed step on the +/// 0.3.17 pair (p1-3080: 29 of 29 proofs died at the memory wall, device_used 9,859 of 9,885 MiB, 0 paid in 2,167 +/// claims), so the prover REFUSES to start, Settings or not, unless an NVIDIA card of 12 GB or more is present, with +/// the reason shown; the lower-memory SP1 threshold is being measured on a rented 3080 and moves this line when +/// it lands. `nvidia-smi` reports a 12 GB card at about 12,208 MiB, a 10 GB card at about 10,240. +pub const MIN_VRAM_MB_PROVE_ANY: u64 = 11_800; +/// The sentence the Proving tile and the log carry when the rule refuses (verbatim from main; the kit's box-prover +/// says the same). +pub const PROVE_UNDER_12GB_LINE: &str = "proving needs a 12 GB card; mining continues"; + +/// The rule above as one question: None when a present NVIDIA card of 12 GB or more exists (or when no NVIDIA card +/// is present at all, since then the CPU and Apple paths decide), Some(the sentence) when every present NVIDIA card is +/// under 12 GB. +pub fn prove_refused_under_12gb(cards: &[CardState]) -> Option<&'static str> { + let nvidia: Vec<&CardState> = cards.iter().filter(|c| c.vendor == "nvidia" && c.present()).collect(); + if nvidia.is_empty() || nvidia.iter().any(|c| c.vram_mb >= MIN_VRAM_MB_PROVE_ANY) { None } else { Some(PROVE_UNDER_12GB_LINE) } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct Decision { pub on: bool, @@ -166,4 +184,22 @@ mod tests { let d = decide(&[idle("nvidia", "RTX 4090", 24_564), card("nvidia", "RTX 5090", 32_607)], "linux", None, None); assert!(d.line.contains("RTX 5090 (32 GB, mining too)"), "{}", d.line); } + + #[test] + fn the_prover_refuses_every_nvidia_card_under_12gb_and_says_why() { + let c3080 = card("nvidia", "NVIDIA GeForce RTX 3080", 10_240); + assert_eq!(prove_refused_under_12gb(&[c3080.clone()]), Some(PROVE_UNDER_12GB_LINE)); + // a 12 GB card beside it lifts the refusal (nvidia-smi reports a 12 GB card at 12,208) + let c3080_12 = card("nvidia", "NVIDIA GeForce RTX 3080 12GB", 12_208); + assert_eq!(prove_refused_under_12gb(&[c3080.clone(), c3080_12]), None); + // an idle 24 GB card lifts it too + let c3090 = idle("nvidia", "NVIDIA GeForce RTX 3090", 24_564); + assert_eq!(prove_refused_under_12gb(&[c3080.clone(), c3090]), None); + // no NVIDIA card at all: not this rule's question (Apple and AMD have their own sentences) + assert_eq!(prove_refused_under_12gb(&[card("amd", "AMD Radeon RX 9070 XT", 16_368), card("apple", "Apple M5 Max", 0)]), None); + // a card that left the machine does not count either way + let mut gone = card("nvidia", "NVIDIA GeForce RTX 3090", 24_564); gone.removed_at = 1.0; + assert_eq!(prove_refused_under_12gb(&[c3080, gone]), Some(PROVE_UNDER_12GB_LINE)); + assert_eq!(PROVE_UNDER_12GB_LINE, "proving needs a 12 GB card; mining continues"); + } } diff --git a/app/igneum-app/src/prover.rs b/app/igneum-app/src/prover.rs index c4a6f41f..47ad1caf 100644 --- a/app/igneum-app/src/prover.rs +++ b/app/igneum-app/src/prover.rs @@ -467,6 +467,21 @@ fn loop_forever(shared: Arc, bin_dir: PathBuf) { } } } + // main's rule (7 October 2026, the fleet's prover roll): a 10 GB card dies at the compressed step every time + // (p1-3080, 29 of 29, 0 paid), so with every present NVIDIA card under 12 GB the prover refuses to start, + // Settings or not, and says why; the measured threshold moves the line (src/provedefault.rs) + if t.cuda { + let cards = shared.state.lock().unwrap().mining.cards.clone(); + if let Some(line) = crate::provedefault::prove_refused_under_12gb(&cards) { + set(&shared, |p| { + p.enabled = true; + p.available = false; + p.status = "off".into(); + p.message = line.into(); + }); + continue; + } + } set(&shared, |p| { p.enabled = true; p.available = true; diff --git a/app/igneum-app/ui/app.js b/app/igneum-app/ui/app.js index 6c372834..b4caf267 100644 --- a/app/igneum-app/ui/app.js +++ b/app/igneum-app/ui/app.js @@ -274,7 +274,7 @@ var View = (function () { ]; var DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; - var SHARD_GB = 20.4, PROVE_GB = 24; + var SHARD_GB = 20.4, PROVE_GB = 24, PROVE_MIN_GB = 12; // PROVE_MIN_GB: main's rule, 7 October 2026 (src/provedefault.rs MIN_VRAM_MB_PROVE_ANY) function page(id) { for (var i = 0; i < PAGES.length; i++) if (PAGES[i].id === id) return PAGES[i]; return PAGES[0]; } function withCommas(n) { return String(Math.round(n || 0)).replace(/\B(?=(\d{3})+(?!\d))/g, ','); } function compact(n) { if (n === null || n === undefined || isNaN(n)) return '0'; var a = Math.abs(n); if (a >= 1e12) return (n / 1e12).toFixed(2) + 'T'; if (a >= 1e9) return (n / 1e9).toFixed(2) + 'G'; if (a >= 1e6) return (n / 1e6).toFixed(2) + 'M'; if (a >= 1e4) return (n / 1e3).toFixed(1) + 'k'; return String(Math.round(n)); } @@ -533,6 +533,7 @@ var View = (function () { function proveTier(cd) { var gb = cd.vram_mb ? Math.round(cd.vram_mb / 1024) : 0; if (cd.vendor === 'apple') return cd.name + ': proves on the CPU, slowly.'; + if (cd.vendor === 'nvidia' && gb > 0 && gb < PROVE_MIN_GB) return cd.name + ': proving needs a 12 GB card; mining continues (' + gb + ' GB).'; if (cd.vendor === 'nvidia') return gb >= PROVE_GB ? cd.name + ': proves while it mines (' + gb + ' GB; a full shard needs ' + SHARD_GB + ' GB).' : cd.name + ': cannot prove a full shard (' + gb + ' GB; a full shard needs ' + SHARD_GB + ' GB).'; return cd.name + ': cannot prove yet (proving needs an NVIDIA card).'; } diff --git a/app/igneum-app/ui/view.test.mjs b/app/igneum-app/ui/view.test.mjs index 82ee155d..b3da2f28 100644 --- a/app/igneum-app/ui/view.test.mjs +++ b/app/igneum-app/ui/view.test.mjs @@ -314,6 +314,8 @@ test('the Tuning card schedule and the goal consequence', () => { test('the prove tier sentence per card, and the counts in one line', () => { assert.equal(V.proveTier(card()), 'NVIDIA GeForce RTX 5090: proves while it mines (32 GB; a full shard needs 20.4 GB).'); assert.equal(V.proveTier(card({ name: 'NVIDIA GeForce RTX 4070', vram_mb: 12288 })), 'NVIDIA GeForce RTX 4070: cannot prove a full shard (12 GB; a full shard needs 20.4 GB).'); + // main's rule, 7 October 2026: under 12 GB the prover refuses and says why (the same sentence as src/provedefault.rs) + assert.equal(V.proveTier(card({ name: 'NVIDIA GeForce RTX 3080', vram_mb: 10240 })), 'NVIDIA GeForce RTX 3080: proving needs a 12 GB card; mining continues (10 GB).'); assert.equal(V.proveTier(card({ name: 'Apple M5 Max', vendor: 'apple' })), 'Apple M5 Max: proves on the CPU, slowly.'); assert.equal(V.proveTier(card({ name: 'AMD Radeon RX 9070 XT', vendor: 'amd', vram_mb: 16384 })), 'AMD Radeon RX 9070 XT: cannot prove yet (proving needs an NVIDIA card).'); assert.equal(V.proveLine({ assigned: 0, submitted: 0, paid: 0, paid_wei: '0' }, false, true), 'Off · not proving · 0 assigned · 0 proven · 0 paid · 0.0000 IGN');