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 }