From bda327b5f5d8f1f8bb7cce92943bb304c5582ccf Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sun, 19 Jul 2026 17:18:49 +0000 Subject: [PATCH] Raise the bloom antipoison FPR cap default to 0.20 The inbound FilterAnnounce cap at 0.10 rejects aggregates that are legitimately near their operating ceiling, before the network reaches the fixed-filter capacity limit. Raise the default to 0.20, which corresponds to fill 0.7248 at k=5, about 2,114 entries on the 1 KB filter (Swamidass-Baldi). Also remove the duplicate default definitions in BloomConfig. Each default was written twice, once in impl Default and once in the serde default function, with nothing enforcing that they agree, so a config file that omits the key took a different path from one that sets it. impl Default now delegates to the serde default functions, leaving a single source of truth. --- docs/design/fips-bloom-filters.md | 4 ++-- docs/reference/configuration.md | 4 ++-- src/config/node.rs | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/design/fips-bloom-filters.md b/docs/design/fips-bloom-filters.md index 1e7f2ca..d0fce16 100644 --- a/docs/design/fips-bloom-filters.md +++ b/docs/design/fips-bloom-filters.md @@ -360,14 +360,14 @@ control socket and `fipstop` dashboard. (See `compute_mesh_size()` in The estimator refuses to produce a value when any contributing filter is above the antipoison FPR cap (`node.bloom.max_inbound_fpr`, -default `0.10`); a partial aggregate would silently underestimate. +default `0.20`); a partial aggregate would silently underestimate. Consumers handle the resulting `None` by displaying an "unknown" state rather than a misleading number. ## Antipoison: Inbound FPR Cap Inbound `FilterAnnounce` payloads are checked against -`node.bloom.max_inbound_fpr` (default `0.10`). Filters whose +`node.bloom.max_inbound_fpr` (default `0.20`). Filters whose estimated false positive rate exceeds the cap are dropped silently (no NACK on the wire) — they would otherwise inflate downstream candidate evaluation cost without contributing useful discrimination. diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index f8de395..35d1f4b 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -277,7 +277,7 @@ Controls tree construction and parent selection. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `node.bloom.update_debounce_ms` | u64 | `500` | Debounce interval for filter update propagation | -| `node.bloom.max_inbound_fpr` | f64 | `0.10` | Antipoison cap: reject inbound `FilterAnnounce` frames whose advertised false-positive rate exceeds this value. Valid range `(0.0, 1.0)`. The default `0.10` corresponds to fill 0.631 at k=5 (≈1,630 entries on the 1 KB filter); a saturated/poisoned filter is still ~100% FPR and rejected | +| `node.bloom.max_inbound_fpr` | f64 | `0.20` | Antipoison cap: reject inbound `FilterAnnounce` frames whose advertised false-positive rate exceeds this value. Valid range `(0.0, 1.0)`. The default `0.20` corresponds to fill 0.7248 at k=5 (≈2,114 entries on the 1 KB filter); a saturated/poisoned filter is still ~100% FPR and rejected | Bloom filter size (1 KB), hash count (5), and size classes are protocol constants and not configurable. @@ -944,7 +944,7 @@ node: flap_dampening_secs: 120 # extended hold-down on flap bloom: update_debounce_ms: 500 - max_inbound_fpr: 0.10 # antipoison cap on inbound FilterAnnounce FPR + max_inbound_fpr: 0.20 # antipoison cap on inbound FilterAnnounce FPR session: default_ttl: 64 pending_packets_per_dest: 16 diff --git a/src/config/node.rs b/src/config/node.rs index 3b1a8bd..f791071 100644 --- a/src/config/node.rs +++ b/src/config/node.rs @@ -635,8 +635,8 @@ pub struct BloomConfig { pub update_debounce_ms: u64, /// Antipoison cap: reject inbound FilterAnnounce whose FPR exceeds /// this value (`node.bloom.max_inbound_fpr`). Valid range `(0.0, 1.0)`. - /// Default `0.10` ≈ fill 0.631 at k=5 ≈ ~1,630 entries on the 1 KB - /// filter (Swamidass–Baldi). Raised from 0.05 so aggregates that are + /// Default `0.20` ≈ fill 0.7248 at k=5 ≈ ~2,114 entries on the 1 KB + /// filter (Swamidass–Baldi). Raised from 0.10 so aggregates that are /// legitimately near their operating ceiling are not rejected before /// the network reaches the fixed-filter capacity limit; conceptually /// distinct from future autoscaling hysteresis setpoints — same unit, @@ -648,8 +648,8 @@ pub struct BloomConfig { impl Default for BloomConfig { fn default() -> Self { Self { - update_debounce_ms: 500, - max_inbound_fpr: 0.10, + update_debounce_ms: Self::default_update_debounce_ms(), + max_inbound_fpr: Self::default_max_inbound_fpr(), } } } @@ -659,7 +659,7 @@ impl BloomConfig { 500 } fn default_max_inbound_fpr() -> f64 { - 0.10 + 0.20 } }