From 340f75fa5eb0f6bee708c88c0099c0497658e2cc Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 18:19:52 +0000 Subject: [PATCH] Pool daemon: jobs kept 60 s or 256 per member (never fewer than 12), the open pool's stale grace 30 s unless set (the Devnet 3 pair, 7 October 2026, 18:16Z: a template every second and a GPU batch outliving the 12-job window, 25,477 unknown_job and 19,119 stale shares, 0 accepted) Co-Authored-By: Claude Fable 5.1 --- pool/src/config.rs | 16 +++++++++++++++- pool/src/node.rs | 6 +++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pool/src/config.rs b/pool/src/config.rs index c2b4e2499..fd14d7cdd 100644 --- a/pool/src/config.rs +++ b/pool/src/config.rs @@ -25,6 +25,8 @@ pub struct Config { pub min_shift: u32, pub max_shift: u32, pub stale_grace_ms: u64, + /// Whether --stale-grace-ms was given (the open pool's default is 30 s, pool-0's 2 s) + pub stale_grace_set: bool, /// A pending block older than this many DAA scores and not blue is an orphan pub orphan_after_daa: u64, pub name: String, @@ -103,6 +105,7 @@ impl Config { min_shift: 0, max_shift: 60, stale_grace_ms: 2000, + stale_grace_set: false, orphan_after_daa: 120, name: "Igneum pool".into(), public_url: String::new(), @@ -149,7 +152,10 @@ impl Config { "--share-interval-s" => c.share_interval_s = val().parse().unwrap_or_else(|_| Config::usage()), "--min-shift" => c.min_shift = val().parse().unwrap_or_else(|_| Config::usage()), "--max-shift" => c.max_shift = val().parse().unwrap_or_else(|_| Config::usage()), - "--stale-grace-ms" => c.stale_grace_ms = val().parse().unwrap_or_else(|_| Config::usage()), + "--stale-grace-ms" => { + c.stale_grace_ms = val().parse().unwrap_or_else(|_| Config::usage()); + c.stale_grace_set = true; + } "--orphan-after-daa" => c.orphan_after_daa = val().parse().unwrap_or_else(|_| Config::usage()), "--name" => c.name = val(), "--public-url" => c.public_url = val(), @@ -207,6 +213,14 @@ impl Config { if c.p2p_listen.is_empty() { c.p2p_listen = format!("0.0.0.0:{}", port + 10); } + // The open pool (Devnet 3 pair, 7 October 2026, 18:16Z: 25,477 unknown_job and 19,119 stale shares, 0 + // accepted): a template arrives every second on a 1-block-a-second chain and a GPU worker's batch outlives + // it, so a share on a template a few seconds old is the normal case, and a share of the share chain is valid + // on any template whose share-chain parent the chain accepts (P2Pool's rule); a share that is also a block on + // an old template is at worst an orphan. The open pool's grace is 30 s unless the operator says otherwise. + if c.open && !c.stale_grace_set { + c.stale_grace_ms = 30_000; + } c } diff --git a/pool/src/node.rs b/pool/src/node.rs index 91381899e..97df4190a 100644 --- a/pool/src/node.rs +++ b/pool/src/node.rs @@ -189,7 +189,11 @@ async fn issue_job(pool: &Arc, member: &Arc, mut raw: RpcRawBlock, open_parent, open_share_target64, }); - while g.jobs.len() > 12 { + // jobs are kept for the share's round trip: 60 s or 256 jobs, never fewer than 12 (the first version kept 12, + // which on a 1-block-a-second chain is about 7 s of jobs, under a GPU worker's batch: every share arrived for + // a job already dropped, "unknown_job" on all of them, the Devnet 3 pair of 7 October 2026) + let keep_from = Instant::now() - Duration::from_secs(60); + while g.jobs.len() > 256 || (g.jobs.len() > 12 && g.jobs.front().is_some_and(|j| j.issued < keep_from)) { g.jobs.pop_front(); } (shift, clean, seeds_changed, share_t)