diff --git a/apps/cuprate/manifest.yml b/apps/cuprate/manifest.yml index bcbf9af2..87a6ffca 100644 --- a/apps/cuprate/manifest.yml +++ b/apps/cuprate/manifest.yml @@ -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 diff --git a/core/archipelago/src/api/rpc/package/dependencies.rs b/core/archipelago/src/api/rpc/package/dependencies.rs index 74e2d474..4c079b16 100644 --- a/core/archipelago/src/api/rpc/package/dependencies.rs +++ b/core/archipelago/src/api/rpc/package/dependencies.rs @@ -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 diff --git a/core/archipelago/src/constants.rs b/core/archipelago/src/constants.rs index bebac5c6..b0957d5b 100644 --- a/core/archipelago/src/constants.rs +++ b/core/archipelago/src/constants.rs @@ -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; diff --git a/core/archipelago/src/container/prod_orchestrator.rs b/core/archipelago/src/container/prod_orchestrator.rs index 4ce990fc..8f388ee2 100644 --- a/core/archipelago/src/container/prod_orchestrator.rs +++ b/core/archipelago/src/container/prod_orchestrator.rs @@ -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 diff --git a/releases/app-catalog.json b/releases/app-catalog.json index a8029499..706e90a6 100644 --- a/releases/app-catalog.json +++ b/releases/app-catalog.json @@ -1315,13 +1315,13 @@ }, "dependencies": [ { - "storage": "300Gi" + "storage": "450Gi" } ], "resources": { "cpu_limit": 0, "memory_limit": "10Gi", - "disk_limit": "300Gi" + "disk_limit": "450Gi" }, "security": { "capabilities": [],