lib/machine/src/qualification.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const admission = @import("admission/root.zig");
2 const instance = @import("instance/root.zig");
3 const machine_root = @import("root.zig");
4 const os = @import("os");
5 const profile = @import("profile/root.zig");
6 const reference = @import("machine_reference");
7 const std = @import("std");
8
9 const Artifact = struct {
10 elf: []const u8,
11 execution_manifest: []const u8,
12 };
13
14 const artifacts = [_]Artifact{
15 .{
16 .elf = @embedFile("machine-k0-elf"),
17 .execution_manifest = @embedFile("machine-k0-manifest"),
18 },
19 .{
20 .elf = @embedFile("machine-k0-release-safe-elf"),
21 .execution_manifest = @embedFile("machine-k0-release-safe-manifest"),
22 },
23 .{
24 .elf = @embedFile("machine-k0-release-fast-elf"),
25 .execution_manifest = @embedFile("machine-k0-release-fast-manifest"),
26 },
27 .{
28 .elf = @embedFile("machine-k0-release-small-elf"),
29 .execution_manifest = @embedFile("machine-k0-release-small-manifest"),
30 },
31 };
32
33 var ram: [instance.ram_bytes]u8 align(instance.ram_alignment) = undefined;
34
35 test {
36 _ = @import("explore/test.zig");
37 _ = @import("profiling/qualification/test.zig");
38 }
39
40 test "qualification profile covers the complete nondeterminism surface" {
41 const selected = profile.interpretedContinuationTestV1();
42 try profile.validate(selected);
43 try profile.auditDeterminism(
44 selected.contract.determinism,
45 &machine_root.determinism_sources,
46 );
47 }
48
49 test "portable reference backend executes every admitted K0 mode" {
50 try expectCompleteCapabilities();
51 var receipts: [artifacts.len]instance.QuiescenceReceipt = undefined;
52 for (artifacts, 0..) |artifact, index| {
53 receipts[index] = try executeReceipt(artifact);
54 try instance.verifyQuiescenceReceipt(
55 receipts[index],
56 receipts[index].fence,
57 );
58 }
59 for (receipts[1..]) |receipt| {
60 try expectSemanticEquivalence(receipts[0], receipt);
61 }
62 for (receipts, 0..) |receipt, index| {
63 for (receipts[0..index]) |prior| {
64 try expectDistinctArtifactIdentity(prior, receipt);
65 }
66 }
67 }
68
69 fn expectCompleteCapabilities() !void {
70 var report: reference.CapabilityReport = .{};
71 for (artifacts) |artifact| {
72 const execution = try os.boot.kernel.manifest.parse(
73 artifact.execution_manifest,
74 );
75 report.merge(reference.capabilityReport(execution, artifact.elf));
76 }
77 try std.testing.expectEqualDeep(reference.CapabilityReport{}, report);
78 }
79
80 fn executeReceipt(artifact: Artifact) !instance.QuiescenceReceipt {
81 const execution = try os.boot.kernel.manifest.parse(
82 artifact.execution_manifest,
83 );
84 var storage = instance.Storage.init();
85 const selected = input(artifact, execution);
86 var machine = switch (instance.Instance.init(&storage, &ram, selected)) {
87 .ready => |value| value,
88 .unavailable => return error.UnexpectedBackendUnavailable,
89 .rejected => |failure| return failure,
90 };
91 defer machine.deinit();
92 try std.testing.expectEqualDeep(
93 instance.Exit{ .doorbell = .{ .code = .ready } },
94 try machine.run(),
95 );
96 var batch: instance.EventBatch = undefined;
97 try machine.takeEvents(&batch);
98 const delivery = try receiptDelivery(&machine, selected.fence);
99 try machine.deliverAdmitted(&delivery);
100 try std.testing.expectEqualDeep(
101 instance.Exit{ .doorbell = .{ .code = .quiescent } },
102 try machine.run(),
103 );
104 try machine.takeEvents(&batch);
105 try machine.acknowledge(delivery.receipt);
106 const receipt = try machine.quiescenceReceipt();
107 try std.testing.expectEqualSlices(
108 u8,
109 &instance.eventTranscriptDigest(&batch),
110 &receipt.event_transcript_digest,
111 );
112 return receipt;
113 }
114
115 fn expectSemanticEquivalence(
116 expected: instance.QuiescenceReceipt,
117 actual: instance.QuiescenceReceipt,
118 ) !void {
119 try std.testing.expect(std.meta.eql(expected.fence, actual.fence));
120 try std.testing.expect(std.meta.eql(expected.delivery, actual.delivery));
121 try std.testing.expect(std.meta.eql(
122 expected.admission_receipt,
123 actual.admission_receipt,
124 ));
125 try std.testing.expect(std.meta.eql(expected.basis, actual.basis));
126 try std.testing.expect(std.meta.eql(expected.block_root, actual.block_root));
127 try std.testing.expect(std.meta.eql(expected.boundary, actual.boundary));
128 try std.testing.expect(std.meta.eql(expected.settled, actual.settled));
129 try std.testing.expect(std.meta.eql(expected.k0, actual.k0));
130 try std.testing.expectEqualSlices(
131 u8,
132 &expected.event_transcript_digest,
133 &actual.event_transcript_digest,
134 );
135 try std.testing.expectEqualSlices(
136 u8,
137 &expected.semantic_transcript_digest,
138 &actual.semantic_transcript_digest,
139 );
140 }
141
142 fn expectDistinctArtifactIdentity(
143 left: instance.QuiescenceReceipt,
144 right: instance.QuiescenceReceipt,
145 ) !void {
146 try std.testing.expect(!std.mem.eql(u8, &left.image_digest, &right.image_digest));
147 try std.testing.expect(!std.mem.eql(
148 u8,
149 &left.execution_fingerprint.digest,
150 &right.execution_fingerprint.digest,
151 ));
152 try std.testing.expect(!std.mem.eql(u8, &left.fenced_digest, &right.fenced_digest));
153 }
154
155 fn receiptDelivery(
156 machine: *const instance.Instance,
157 fence: os.abi.ActivationFence,
158 ) !admission.Delivery {
159 const admitted = try admission.prepare(
160 try machine.admissionBasis(),
161 try admission.terminal(0, os.k0.request_bytes),
162 );
163 return admission.bindDelivery(admitted, @splat(0x88), fence);
164 }
165
166 fn input(
167 artifact: Artifact,
168 execution: os.boot.kernel.manifest.View,
169 ) instance.Input {
170 return .{
171 .profile = profile.interpretedContinuationTestV1(),
172 .elf = artifact.elf,
173 .execution_manifest = artifact.execution_manifest,
174 .expected_execution_fingerprint = execution.header.fingerprint,
175 .fence = .{
176 .world = @splat(0x44),
177 .generation = 1,
178 .token = @splat(0x55),
179 },
180 .initial_time_tick = 7,
181 .entropy_generation = 1,
182 .terminal_offset = 0,
183 .effect_frontier = 0,
184 .block_root = @splat(0x33),
185 .source_root = @splat(0x77),
186 .input_frontier = 0,
187 .terminal_input_offset = 0,
188 .outstanding_effect = null,
189 };
190 }