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_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
|
// L1 QVL (Quasar Vector Lattice) - Advanced Graph Engine
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
@ -221,6 +238,19 @@ pub fn build(b: *std.Build) void {
|
||||||
l1_did_tests.linkLibC();
|
l1_did_tests.linkLibC();
|
||||||
const run_l1_did_tests = b.addRunArtifact(l1_did_tests);
|
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
|
// Import PQXDH into main L1 module
|
||||||
|
|
||||||
// Tests (root is test_pqxdh.zig)
|
// 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_entropy_tests.step);
|
||||||
test_step.dependOn(&run_l1_prekey_tests.step);
|
test_step.dependOn(&run_l1_prekey_tests.step);
|
||||||
test_step.dependOn(&run_l1_did_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_vector_tests.step);
|
||||||
test_step.dependOn(&run_l1_pqxdh_tests.step);
|
test_step.dependOn(&run_l1_pqxdh_tests.step);
|
||||||
test_step.dependOn(&run_utcp_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