lib/machine/src/explore/distributed/seed.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const explore = @import("../root.zig");
2 const profile = @import("../../profile/root.zig");
3 const std = @import("std");
4 const types = @import("types.zig");
5
6 const Sha256 = std.crypto.hash.sha2.Sha256;
7 const domain = "tiny.machine.explore.distributed.seed/v1";
8
9 pub const Provenance = types.Provenance;
10
11 pub fn selected() profile.Profile {
12 return profile.interpretedContinuationTestV1();
13 }
14
15 pub fn provenance(value: profile.Profile) profile.Error!Provenance {
16 try profile.validate(value);
17 const full = try profile.profileFingerprint(value);
18 const contract = try profile.contractFingerprint(value);
19 const determinism = value.contract.determinism;
20 var hasher = Sha256.init(.{});
21 hasher.update(domain);
22 hasher.update(&full.digest);
23 hasher.update(&contract.digest);
24 hasher.update(&determinism.digest);
25 var encoded: [6]u8 = undefined;
26 std.mem.writeInt(u16, encoded[0..2], @backingInt(determinism.schema), .little);
27 std.mem.writeInt(u16, encoded[2..4], determinism.entry_count, .little);
28 std.mem.writeInt(u16, encoded[4..6], types.dialect_version, .little);
29 hasher.update(&encoded);
30 var bytes: [Sha256.digest_length]u8 = undefined;
31 hasher.final(&bytes);
32 std.debug.assert(!allZero(&bytes));
33 return .{
34 .profile = full,
35 .contract = contract,
36 .determinism = determinism,
37 .dialect = types.dialect_version,
38 .seed = .{ .bytes = bytes },
39 };
40 }
41
42 fn allZero(bytes: []const u8) bool {
43 for (bytes) |byte| if (byte != 0) return false;
44 return true;
45 }
46
47 test "distributed seed derives only from the frozen profile identity" {
48 const value = selected();
49 const first = try provenance(value);
50 const second = try provenance(value);
51 try std.testing.expectEqualDeep(first, second);
52 try std.testing.expectEqual(explore.SeedDialect.sha256_v1, first.seed.dialect);
53 try std.testing.expect(!allZero(&first.seed.bytes));
54 try std.testing.expectEqualDeep(
55 profile.determinism.inventory_identity,
56 first.determinism,
57 );
58 const other = try provenance(profile.interpretedReconstructV1());
59 try std.testing.expect(!std.mem.eql(u8, &first.seed.bytes, &other.seed.bytes));
60 }