//! Quasar Vector (RFC-0120) //! //! The atomic unit of communication in QVL. Replaces "transactions". //! vectors are Events. //! //! Structure: //! - Source DID (32 bytes) //! - Target DID (32 bytes) //! - Vector Type (2 bytes) //! - Payload Hash (32 bytes) //! - Payload (Optional) //! - Signature (64 bytes) -- covers above fields //! - Trust Path (ProofOfPath) -- hardening //! - Entropy Proof (EntropyStamp) -- anti-spam //! - Timestamp (SovereignTimestamp) //! - Graphology (Meta) //! - Nonce (8 bytes) const std = @import("std"); const l0_transport = @import("l0_transport"); const proof_of_path = @import("proof_of_path.zig"); const soulkey = @import("soulkey.zig"); const entropy = @import("entropy.zig"); const trust_graph = @import("trust_graph.zig"); /// Vector Type (RFC-0120 S4.2) pub const VectorType = enum(u16) { // Communication (0x0700-0x070F) message = 0x0700, message_ack = 0x0701, // Value Transfer (0x0710-0x071F) - triggers L2 value_transfer = 0x0710, value_receipt = 0x0711, // Credentials (0x0720-0x072F) credential_issue = 0x0720, credential_revoke = 0x0721, // Trust Graph (0x0730-0x073F) trust_grant = 0x0730, trust_revoke = 0x0731, trust_delegate = 0x0732, // Anchoring (0x0740-0x074F) anchor_commit = 0x0740, anchor_proof = 0x0741, // Explorer (0x0750-0x075F) explorer_probe = 0x0750, explorer_signal = 0x0751, }; /// Graphology Metadata (8 bytes) /// Measures the "shape" of the relationship pub const GraphologyMeta = packed struct { trust_depth: u8, // 0 = direct, 255 = void mutual_contacts: u8, // Shared nodes (capped at 255) path_reputation: u16, // 0-65535 scaled to 0.0-1.0 flags: GraphologyFlags, // Bit flags (4 bytes padding/flags) }; pub const GraphologyFlags = packed struct { first_contact: bool, whitelisted: bool, blacklisted: bool, from_void: bool, degraded_path: bool, _pad: u27, }; /// The Quasar Vector pub const QuasarVector = struct { // === Identity (64 bytes) === source_did: [32]u8, target_did: [32]u8, // 0x00 for broadcast // === Type (2 bytes) === vector_type: VectorType, // === Payload === payload_hash: [32]u8, payload: ?[]u8, // Optional content // === Authentication === signature: [64]u8, // Ed25519 over body trust_path: ?proof_of_path.ProofOfPath, // Optional for direct peers entropy_stamps: std.ArrayListUnmanaged(entropy.EntropyStamp), // PoW // === Metadata === created_at: l0_transport.time.SovereignTimestamp, // Creation time graphology: GraphologyMeta, nonce: u64, // Replay protection allocator: std.mem.Allocator, pub fn init(allocator: std.mem.Allocator) QuasarVector { return .{ .source_did = [_]u8{0} ** 32, .target_did = [_]u8{0} ** 32, .vector_type = .message, .payload_hash = [_]u8{0} ** 32, .payload = null, .signature = [_]u8{0} ** 64, .trust_path = null, .entropy_stamps = .{}, .created_at = l0_transport.time.SovereignTimestamp.now(), .graphology = std.mem.zeroes(GraphologyMeta), .nonce = std.crypto.random.int(u64), // Secure random nonce .allocator = allocator, }; } pub fn deinit(self: *QuasarVector) void { if (self.payload) |p| self.allocator.free(p); if (self.trust_path) |*tp| tp.deinit(); self.entropy_stamps.deinit(self.allocator); } /// Sign the vector (Ed25519) /// Signs: source || target || type || hash || created_at || nonce pub fn sign(self: *QuasarVector, sk: *const soulkey.SoulKey) !void { var msg = std.ArrayListUnmanaged(u8){}; defer msg.deinit(self.allocator); const writer = msg.writer(self.allocator); try writer.writeAll(&self.source_did); try writer.writeAll(&self.target_did); try writer.writeInt(u16, @intFromEnum(self.vector_type), .little); try writer.writeAll(&self.payload_hash); try writer.writeAll(&self.created_at.serialize()); try writer.writeInt(u64, self.nonce, .little); const sig = try sk.sign(msg.items); self.signature = sig; } /// Verify signature pub fn verifySignature(self: *const QuasarVector) bool { var msg = std.ArrayListUnmanaged(u8){}; defer msg.deinit(self.allocator); const writer = msg.writer(self.allocator); writer.writeAll(&self.source_did) catch return false; writer.writeAll(&self.target_did) catch return false; writer.writeInt(u16, @intFromEnum(self.vector_type), .little) catch return false; writer.writeAll(&self.payload_hash) catch return false; writer.writeAll(&self.created_at.serialize()) catch return false; writer.writeInt(u64, self.nonce, .little) catch return false; return soulkey.SoulKey.verify(self.source_did, msg.items, self.signature) catch false; } /// Full Validation Pipeline (Reality Tunnel Hook) /// Checks: Signature, Time, Trust Path pub fn validate( self: *const QuasarVector, graph: *const trust_graph.CompactTrustGraph, ) ValidationResult { // 1. Signature Check if (!self.verifySignature()) return .invalid_signature; // 2. Time Check const now = l0_transport.time.SovereignTimestamp.now(); switch (self.created_at.validateForVector(now)) { .valid => {}, .too_far_future => return .future_timestamp, .too_old => return .expired, } // 3. Trust Check // If ProofOfPath provided, verify it if (self.trust_path) |*pop| { const verdict = pop.verify(self.target_did, self.source_did, graph); if (verdict != .valid) return .invalid_trust_path; } else { // No proof provided - check direct trust if (!graph.hasDirectTrustByDid(self.target_did, self.source_did)) { return .unknown_sender; // Airlock rejection } } return .valid; } pub const ValidationResult = enum { valid, invalid_signature, future_timestamp, expired, invalid_trust_path, unknown_sender, }; /// Set Payload pub fn setPayload(self: *QuasarVector, data: []const u8) !void { if (self.payload) |p| self.allocator.free(p); self.payload = try self.allocator.dupe(u8, data); std.crypto.hash.Blake3.hash(data, &self.payload_hash, .{}); } }; // ============================================================================ // TESTS // ============================================================================ test "QuasarVector: init and sign" { const allocator = std.testing.allocator; // Create a keypair var sk = try soulkey.SoulKey.generate(); var vector = QuasarVector.init(allocator); defer vector.deinit(); vector.source_did = sk.ed25519_public; try vector.setPayload("Hello QVL!"); // Sign try vector.sign(&sk); // Verify try std.testing.expect(vector.verifySignature()); // Tamper vector.nonce += 1; try std.testing.expect(!vector.verifySignature()); } test "QuasarVector: validation flow" { const allocator = std.testing.allocator; // Setup: Receiver trusts A. A trusts Sender. // Sender sends vector to Receiver with ProofOfPath(R->A->S). // 1. Keys const k_r = try soulkey.SoulKey.generate(); // Receiver const k_a = try soulkey.SoulKey.generate(); // Intermediary var k_s = try soulkey.SoulKey.generate(); // Sender // 2. Receiver's Trust Graph var graph = try trust_graph.CompactTrustGraph.init(allocator, k_r.ed25519_public, .{}); defer graph.deinit(); try graph.grantTrust(k_a.ed25519_public, .full, .friends, 0); // Manual edge in graph for path finding (A->S) const a_idx = graph.getNode(k_a.ed25519_public).?; const s_idx = try graph.getOrInsertNode(k_s.ed25519_public); try graph.adjacency.items[a_idx].append(allocator, .{ .target_idx = s_idx, .level = .full, .visibility = .public, .expires_at = 0 }); // 3. Sender creates Vector var vector = QuasarVector.init(allocator); defer vector.deinit(); vector.source_did = k_s.ed25519_public; vector.target_did = k_r.ed25519_public; try vector.sign(&k_s); // 4. Validation (Should fail: unknown sender, no proof) try std.testing.expectEqual(QuasarVector.ValidationResult.unknown_sender, vector.validate(&graph)); // 5. Add Proof const pop = try proof_of_path.ProofOfPath.construct(allocator, k_s.ed25519_public, k_r.ed25519_public, &graph); vector.trust_path = pop; // 6. Validation (Should pass) try std.testing.expectEqual(QuasarVector.ValidationResult.valid, vector.validate(&graph)); }