libertaria-stack/l0-transport/quarantine.zig

79 lines
2.3 KiB
Zig

//! Quarantine List - Active Defense Enforcement
//!
//! Maintains a list of locally blocked/monitored DIDs based on SlashSignals.
const std = @import("std");
/// Status of a quarantined node
pub const QuarantineStatus = enum {
None, // Not quarantined
Blocked, // Drop all traffic
Honeypot, // Accept traffic, log analysis, send fake OKs?
};
pub const QuarantineEntry = struct {
until_ts: i64,
mode: QuarantineStatus,
reason: u8,
};
/// High-performance blocking list
pub const QuarantineList = struct {
allocator: std.mem.Allocator,
// Using u256 to represent [32]u8 DID as key for HashMap
lookup: std.AutoHashMap(u256, QuarantineEntry),
pub fn init(allocator: std.mem.Allocator) QuarantineList {
return QuarantineList{
.allocator = allocator,
.lookup = std.AutoHashMap(u256, QuarantineEntry).init(allocator),
};
}
pub fn deinit(self: *QuarantineList) void {
self.lookup.deinit();
}
/// Add a node to quarantine
pub fn add(self: *QuarantineList, did: [32]u8, mode: QuarantineStatus, duration_sec: i64, reason: u8) !void {
const key = std.mem.readInt(u256, &did, .little);
const now = std.time.timestamp();
const entry = QuarantineEntry{
.until_ts = now + duration_sec,
.mode = mode,
.reason = reason,
};
try self.lookup.put(key, entry);
}
/// Check status of a node
pub fn check(self: *const QuarantineList, did: [32]u8) QuarantineStatus {
const key = std.mem.readInt(u256, &did, .little);
if (self.lookup.get(key)) |entry| {
const now = std.time.timestamp();
if (now > entry.until_ts) {
// Expired
return .None;
}
return entry.mode;
}
return .None;
}
};
test "quarantine list basic" {
var list = QuarantineList.init(std.testing.allocator);
defer list.deinit();
// Valid hex for u8 (0xBB)
const bad_did = [_]u8{0xBB} ** 32;
try list.add(bad_did, .Blocked, 3600, 1);
try std.testing.expectEqual(QuarantineStatus.Blocked, list.check(bad_did));
const good_did = [_]u8{0xAA} ** 32;
try std.testing.expectEqual(QuarantineStatus.None, list.check(good_did));
}