fix: XDP unsafe loader + Redis sync; enforce 250-line/4-file layout limits
- xdp: CString for if_nametoindex (was UB), real detach via prog fd (fabricated borrow_raw(-1) silently never detached), SAFETY comments, saturating expiry math; +5 unit tests - redis: real pubsub reconnect with exponential backoff (was sleep+return); KEYS -> SCAN in heartbeat sweep - ci: cargo test --all-features, repo-gates job — module size gate (scripts/check_module_size.sh, ratchet baseline) + default-secrets grep - refactor src/ to <=250 LOC/file, <=4 .rs/dir without behavior change; thin bins (rampart.rs 330 -> 6 LOC), new app/, subnet/, intel/, profile/, prefix/, challenge/, filter/, probe/, inventory/, metrics/, node/ - docs: TODO v5.0 (status refresh, new rules, findings backlog), README quickstart now matches real binaries - verify: fmt/clippy -D warnings/test --all-features (164 tests)/clang XDP green
This commit is contained in:
parent
d6bcae54c8
commit
aa615a1141
64 changed files with 2052 additions and 1408 deletions
88
src/engine/challenge/difficulty.rs
Normal file
88
src/engine/challenge/difficulty.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
use crate::metrics;
|
||||
use std::collections::VecDeque;
|
||||
use std::time::Instant;
|
||||
|
||||
/// Адаптирует сложность PoW к текущему темпу подключений.
|
||||
pub struct DifficultyAdjuster {
|
||||
window: VecDeque<Instant>,
|
||||
min: u8,
|
||||
max: u8,
|
||||
current: u8,
|
||||
}
|
||||
|
||||
impl Default for DifficultyAdjuster {
|
||||
fn default() -> Self {
|
||||
Self::new(4, 10)
|
||||
}
|
||||
}
|
||||
|
||||
impl DifficultyAdjuster {
|
||||
#[must_use]
|
||||
pub fn new(min: u8, max: u8) -> Self {
|
||||
Self {
|
||||
window: VecDeque::new(),
|
||||
min: min.max(4),
|
||||
max: max.min(10),
|
||||
current: min.max(4),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_connection(&mut self) {
|
||||
let now = Instant::now();
|
||||
self.window.push_back(now);
|
||||
while let Some(&t) = self.window.front() {
|
||||
if now.duration_since(t).as_secs() >= 1 {
|
||||
self.window.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let new_diff = self.compute_difficulty();
|
||||
if self.current != new_diff {
|
||||
tracing::info!(
|
||||
old = self.current,
|
||||
new = new_diff,
|
||||
window = self.window.len(),
|
||||
"pow: difficulty adjusted"
|
||||
);
|
||||
self.current = new_diff;
|
||||
metrics::POW_CURRENT_DIFFICULTY.set(self.current as i64);
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn current_difficulty(&self) -> u8 {
|
||||
metrics::POW_CURRENT_DIFFICULTY.set(self.current as i64);
|
||||
self.current
|
||||
}
|
||||
|
||||
fn compute_difficulty(&self) -> u8 {
|
||||
match self.window.len() {
|
||||
cps if cps > 500 => self.max.max(self.min),
|
||||
cps if cps > 200 => 8,
|
||||
cps if cps > 50 => 6,
|
||||
_ => self.min,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn adjuster_raises_difficulty_under_load() {
|
||||
let mut adjuster = DifficultyAdjuster::new(4, 10);
|
||||
for _ in 0..600 {
|
||||
adjuster.record_connection();
|
||||
}
|
||||
assert_eq!(adjuster.current_difficulty(), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adjuster_stays_minimal_when_idle() {
|
||||
let mut adjuster = DifficultyAdjuster::new(4, 10);
|
||||
adjuster.record_connection();
|
||||
assert_eq!(adjuster.current_difficulty(), 4);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue