refactor(cuprate): one CUPRATE_MIN_DISK_GB, manifest matches it (review)

450 existed as two independent Rust constants (RPC gates vs boot
reconciler) linked only by a "keep in lockstep" comment — updating one
would reopen the disk-fill hole. Move it to crate::constants as the
single source of truth both paths import.

Also raise apps/cuprate/manifest.yml storage dependency and disk_limit
from 300Gi to 450Gi so manifest-driven surfaces (store size, pre-checks)
show the number the gate actually enforces — a user provisioning to the
displayed 300 was refused at an unexplained 450. Catalog regenerated
(cuprate entry re-embedded; still unsigned pending sign-catalog.sh).
This commit is contained in:
2026-09-12 16:14:55 -04:00
committed by archipelago
parent 047ef98987
commit 86052d9552
5 changed files with 40 additions and 24 deletions
+12 -4
View File
@@ -44,12 +44,18 @@ app:
# when disk is scarce (see the DISK_GB branch in
# apps/bitcoin-knots/manifest.yml). Left running on a too-small disk it
# syncs until the filesystem fills and takes Archipelago down. The
# disk-scarce equivalent is enforced in Rust instead: install/start
# refuse, and boot reconcile skips, on any node under
# disk-scarce equivalent is enforced in Rust instead: install, start,
# restart and update refuse, and boot reconcile skips, on any node under
# CUPRATE_MIN_DISK_GB (450GB — chain + headroom; refuses the 250GB VPS
# class, allows 500GB-class disks). If upstream ever ships a prune flag,
# replace that gate with the bitcoin-style entrypoint branch.
- storage: 300Gi
#
# 450Gi, not the chain size (~250GiB): every manifest-driven surface
# (store size display, install pre-checks, docs) must show the number the
# Rust gate actually enforces, or a user provisioned to the displayed
# value gets refused at a different, unexplained one. Single source of
# truth is crate::constants::CUPRATE_MIN_DISK_GB — keep in lockstep.
- storage: 450Gi
resources:
cpu_limit: 0
@@ -59,7 +65,9 @@ app:
# CPU and ~595GB/24h of block I/O on a fully-synced node. 10Gi leaves
# headroom above the 8GiB cache for the process itself.
memory_limit: 10Gi
disk_limit: 300Gi
# Matches the storage dependency above (= the enforced disk floor),
# not the raw chain size — see the CUPRATE_MIN_DISK_GB note.
disk_limit: 450Gi
security:
# FROM scratch, no package manager/shell, ownership fixed at build time
@@ -670,15 +670,11 @@ async fn detect_disk_gb() -> u64 {
.unwrap_or(u64::MAX)
}
/// Smallest disk (GB, total) a cuprate node can live on. Monero mainnet is
/// ~250 GiB of chain data in 2026 and grows ~60 GiB/year; cuprated's storage
/// (block blobs + fjall index + logs) needs headroom above the raw chain.
/// 450 lets a 500 GB-class disk work while refusing the 250 GB VPS class,
/// where the chain does not fit at all.
///
/// Kept in lockstep with `prod_orchestrator::CUPRATE_MIN_DISK_GB` — same
/// duplication pattern as `ARCHIVAL_BITCOIN_DISK_GB` above.
pub(super) const CUPRATE_MIN_DISK_GB: u64 = 450;
/// Smallest disk (GB, total) a cuprate node can live on. The value and its
/// rationale live in ONE place — `crate::constants::CUPRATE_MIN_DISK_GB` —
/// shared with the boot reconciler so install/start and boot can never
/// disagree about where cuprate may run.
use crate::constants::CUPRATE_MIN_DISK_GB;
/// The bitcoin apps pick `-prune` automatically when disk is scarce, because
/// bitcoind supports pruning. Cuprate CANNOT: upstream has no pruning config
+16
View File
@@ -9,3 +9,19 @@ pub const DWN_HEALTH_URL: &str = "http://127.0.0.1:3100/health";
/// Tor SOCKS5 proxy for outbound onion connections.
pub const TOR_SOCKS_PROXY: &str = "socks5h://127.0.0.1:9050";
/// Smallest disk (GB, total) a cuprate node may be installed, started,
/// restarted, updated, or boot-reconciled onto. Cuprate has no on-disk
/// pruning (verified against upstream `cuprated/src/config.rs` — the
/// `pruning` crate is Monero's p2p protocol pruning), so unlike the bitcoin
/// apps it cannot self-shrink on a scarce disk; below this line the ~250 GiB
/// Monero chain simply does not fit and running it would fill the filesystem
/// and take Archipelago down. 450 = chain + growth/headroom: allows
/// 500 GB-class disks, refuses the 250 GB VPS class.
///
/// SINGLE SOURCE OF TRUTH — the RPC gates
/// (`api::rpc::package::dependencies`) and the boot reconciler
/// (`container::prod_orchestrator`) both read this; a drift between them
/// would silently reopen the disk-fill failure the gate exists to close.
/// Keep `apps/cuprate/manifest.yml` (storage dependency + comments) aligned.
pub const CUPRATE_MIN_DISK_GB: u64 = 450;
@@ -49,15 +49,11 @@ use crate::update::host_sudo;
/// so the rule is visible in one place and unit-testable.
const UI_APP_IDS: &[&str] = &["bitcoin-ui", "electrs-ui", "lnd-ui", "cuprate-ui"];
const ARCHIVAL_BITCOIN_DISK_GB: u64 = 1000;
/// Smallest disk (GB, total) a cuprate node may run on. Cuprate cannot prune
/// (upstream has no on-disk pruning — the bitcoin apps self-prune via their
/// entrypoint, cuprated has no equivalent flag), so a node too small for the
/// ~250 GiB Monero chain must not sync it at all: left running, it fills the
/// filesystem and takes Archipelago down. Install/start carry the same gate
/// (`dependencies::CUPRATE_MIN_DISK_GB`); this one covers boot reconcile, so
/// an already-installed cuprate on a shrunken/remounted disk stays down
/// instead of resuming a doomed sync.
const CUPRATE_MIN_DISK_GB: u64 = 450;
// The cuprate disk floor is `crate::constants::CUPRATE_MIN_DISK_GB` — one
// value shared with the install/start/restart/update RPC gates so boot
// reconcile can never resume below the line they refuse at.
use crate::constants::CUPRATE_MIN_DISK_GB;
fn requires_cuprate_disk(app_id: &str, disk_gb: u64) -> bool {
app_id == "cuprate" && disk_gb < CUPRATE_MIN_DISK_GB
+2 -2
View File
@@ -1315,13 +1315,13 @@
},
"dependencies": [
{
"storage": "300Gi"
"storage": "450Gi"
}
],
"resources": {
"cpu_limit": 0,
"memory_limit": "10Gi",
"disk_limit": "300Gi"
"disk_limit": "450Gi"
},
"security": {
"capabilities": [],