Phase 7 Sprint 1&2: SlashSignal and QuarantineList
- Implemented l1-identity/slash.zig (SlashSignal, PunishmentType) - Implemented l0-transport/quarantine.zig (QuarantineList, Honeypot mode) - Integrated modules into build.zig - Validated with unit tests Ready for enforcement hooks.
This commit is contained in:
parent
1b05a6555c
commit
cc68e4f9a2
32
build.zig
32
build.zig
|
|
@ -126,6 +126,23 @@ pub fn build(b: *std.Build) void {
|
|||
});
|
||||
l1_did_mod.addImport("pqxdh", l1_pqxdh_mod);
|
||||
|
||||
// ========================================================================
|
||||
// L1 Slash Protocol & L0 Quarantine
|
||||
// ========================================================================
|
||||
const l1_slash_mod = b.createModule(.{
|
||||
.root_source_file = b.path("l1-identity/slash.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
l1_mod.addImport("slash", l1_slash_mod);
|
||||
|
||||
const l0_quarantine_mod = b.createModule(.{
|
||||
.root_source_file = b.path("l0-transport/quarantine.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
utcp_mod.addImport("quarantine", l0_quarantine_mod);
|
||||
|
||||
// ========================================================================
|
||||
// L1 QVL (Quasar Vector Lattice) - Advanced Graph Engine
|
||||
// ========================================================================
|
||||
|
|
@ -221,6 +238,19 @@ pub fn build(b: *std.Build) void {
|
|||
l1_did_tests.linkLibC();
|
||||
const run_l1_did_tests = b.addRunArtifact(l1_did_tests);
|
||||
|
||||
// L1 Slash tests
|
||||
const l1_slash_tests = b.addTest(.{
|
||||
.root_module = l1_slash_mod,
|
||||
});
|
||||
l1_slash_tests.linkLibC();
|
||||
const run_l1_slash_tests = b.addRunArtifact(l1_slash_tests);
|
||||
|
||||
// L0 Quarantine tests
|
||||
const l0_quarantine_tests = b.addTest(.{
|
||||
.root_module = l0_quarantine_mod,
|
||||
});
|
||||
const run_l0_quarantine_tests = b.addRunArtifact(l0_quarantine_tests);
|
||||
|
||||
// Import PQXDH into main L1 module
|
||||
|
||||
// Tests (root is test_pqxdh.zig)
|
||||
|
|
@ -318,6 +348,8 @@ pub fn build(b: *std.Build) void {
|
|||
test_step.dependOn(&run_l1_entropy_tests.step);
|
||||
test_step.dependOn(&run_l1_prekey_tests.step);
|
||||
test_step.dependOn(&run_l1_did_tests.step);
|
||||
test_step.dependOn(&run_l1_slash_tests.step);
|
||||
test_step.dependOn(&run_l0_quarantine_tests.step);
|
||||
test_step.dependOn(&run_l1_vector_tests.step);
|
||||
test_step.dependOn(&run_l1_pqxdh_tests.step);
|
||||
test_step.dependOn(&run_utcp_tests.step);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
//! 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));
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//! RFC-0121: Slash Protocol - Detection and Punishment
|
||||
//!
|
||||
//! Defines the SlashSignal structure and verification logic for active defense.
|
||||
|
||||
const std = @import("std");
|
||||
const crypto = @import("std").crypto;
|
||||
|
||||
/// Reason for the slash
|
||||
pub const SlashReason = enum(u8) {
|
||||
BetrayalNegativeCycle = 0x01, // Bellman-Ford detection
|
||||
DoubleSign = 0x02, // Equivocation
|
||||
InvalidProof = 0x03, // Forged check
|
||||
Spam = 0x04, // DoS attempt (L0 triggered)
|
||||
};
|
||||
|
||||
/// Type of punishment requested
|
||||
pub const PunishmentType = enum(u8) {
|
||||
Quarantine = 0x01, // Temporary isolation (honeypot)
|
||||
ReputationSlash = 0x02, // Degradation of trust score
|
||||
Exile = 0x03, // Permanent ban + Bond burning (L3)
|
||||
};
|
||||
|
||||
/// A cryptographic signal announcing a detected betrayal
|
||||
pub const SlashSignal = struct {
|
||||
target_did: [32]u8,
|
||||
reason: SlashReason,
|
||||
punishment: PunishmentType,
|
||||
evidence_hash: [32]u8, // Hash of the proof (or full proof if small)
|
||||
timestamp: i64,
|
||||
nonce: u64,
|
||||
|
||||
/// Serialize to bytes for signing (excluding signature)
|
||||
pub fn serializeForSigning(self: SlashSignal) [82]u8 {
|
||||
var buf: [82]u8 = undefined;
|
||||
// Target DID (32)
|
||||
@memcpy(buf[0..32], &self.target_did);
|
||||
// Reason (1)
|
||||
buf[32] = @intFromEnum(self.reason);
|
||||
// Punishment (1)
|
||||
buf[33] = @intFromEnum(self.punishment);
|
||||
// Evidence Hash (32)
|
||||
@memcpy(buf[34..66], &self.evidence_hash);
|
||||
// Timestamp (8)
|
||||
std.mem.writeInt(i64, buf[66..74], self.timestamp, .little);
|
||||
// Nonce (8)
|
||||
std.mem.writeInt(u64, buf[74..82], self.nonce, .little);
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
test "slash signal serialization" {
|
||||
const signal = SlashSignal{
|
||||
.target_did = [_]u8{1} ** 32,
|
||||
.reason = .BetrayalNegativeCycle,
|
||||
.punishment = .Quarantine,
|
||||
.evidence_hash = [_]u8{0xAA} ** 32,
|
||||
.timestamp = 1000,
|
||||
.nonce = 42,
|
||||
};
|
||||
|
||||
const bytes = signal.serializeForSigning();
|
||||
try std.testing.expectEqual(bytes[0], 1);
|
||||
try std.testing.expectEqual(bytes[32], 0x01); // Reason
|
||||
try std.testing.expectEqual(bytes[33], 0x01); // Punishment
|
||||
try std.testing.expectEqual(bytes[34], 0xAA); // Evidence
|
||||
}
|
||||
Loading…
Reference in New Issue