lib/machine/src/checkpoint/stream/encode.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const core = @import("machine_instance_core");
2 const instance_receipt = @import("../../instance/receipt/root.zig");
3 const os = @import("os");
4 const owner = @import("../owner/root.zig");
5 const schema = @import("schema.zig");
6
7 const wire = os.abi.wire;
8
9 /// Encodes authenticated checkpoint metadata into one fixed 4096-byte header.
10 /// Callers supply the `Contents` that checkpoint inspection returned. The call
11 /// starts from a zero-filled buffer, so every unused byte and every reserved
12 /// range is zero. The function writes the envelope, the checkpoint root and
13 /// memory digest, the settled receipt, the CPU restart frame, and the immutable
14 /// image descriptor.
15 pub fn header(
16 contents: owner.Contents,
17 output: *[schema.header_bytes]u8,
18 ) void {
19 var encoded: [schema.header_bytes]u8 = @splat(0);
20 encodeEnvelope(&encoded);
21 encodeRoot(contents, &encoded);
22 encodeSemantic(contents.material.receipt, &encoded);
23 encodeCpu(contents.material.cpu, &encoded);
24 encodeImmutable(contents.material.immutable_image, &encoded);
25 output.* = encoded;
26 }
27
28 fn encodeEnvelope(output: *[schema.header_bytes]u8) void {
29 const layout = schema.Envelope;
30 @memcpy(output[layout.magic_offset..layout.version_offset], &schema.magic);
31 put16(output, layout.version_offset, schema.version);
32 put16(output, layout.header_bytes_offset, schema.header_bytes);
33 put16(output, layout.flags_offset, schema.flags);
34 put16(output, layout.format_offset, schema.checkpoint_format);
35 put64(output, layout.stream_bytes_offset, schema.encoded_stream_bytes);
36 put64(output, layout.ram_bytes_offset, schema.ram_bytes);
37 put32(output, layout.page_bytes_offset, schema.page_bytes);
38 put16(output, layout.abi_major_offset, schema.abi_major);
39 put16(output, layout.abi_minor_offset, schema.abi_minor);
40 put16(output, layout.load_capacity_offset, schema.load_capacity);
41 put16(output, layout.load_bytes_offset, schema.load_bytes);
42 put16(output, layout.digest_bytes_offset, schema.digest_bytes);
43 put16(output, layout.root_bytes_offset, schema.root_bytes);
44 put16(
45 output,
46 layout.semantic_receipt_bytes_offset,
47 schema.semantic_receipt_bytes,
48 );
49 put16(output, layout.cpu_bytes_offset, schema.cpu_bytes);
50 put16(
51 output,
52 layout.immutable_descriptor_bytes_offset,
53 schema.immutable_descriptor_bytes,
54 );
55 }
56
57 fn encodeRoot(
58 contents: owner.Contents,
59 output: *[schema.header_bytes]u8,
60 ) void {
61 putDigest(output, schema.RootLayout.digest_offset, contents.root.digest);
62 putDigest(
63 output,
64 schema.RootLayout.profile_offset,
65 contents.root.profile.digest,
66 );
67 putDigest(
68 output,
69 schema.RootLayout.state_offset,
70 contents.root.state.digest,
71 );
72 putDigest(
73 output,
74 schema.MemoryLayout.digest_offset,
75 contents.memory.digest,
76 );
77 }
78
79 fn encodeSemantic(
80 value: instance_receipt.SemanticReceipt,
81 output: *[schema.header_bytes]u8,
82 ) void {
83 const layout = schema.SemanticLayout;
84 putDigest(output, layout.admission_offset, value.admission_receipt.digest);
85 putDigest(output, layout.contract_offset, value.basis.contract.digest);
86 putDigest(output, layout.source_root_offset, value.basis.source_root);
87 put64(output, layout.input_frontier_offset, value.basis.frontiers.input);
88 put64(
89 output,
90 layout.terminal_input_offset,
91 value.basis.frontiers.terminal_input_offset,
92 );
93 put64(output, layout.virtual_time_offset, value.basis.frontiers.virtual_time_tick);
94 put64(output, layout.entropy_offset, value.basis.frontiers.entropy_generation);
95 put64(output, layout.effect_offset, value.basis.frontiers.effect);
96 putDigest(output, layout.image_offset, value.image_digest);
97 putDigest(output, layout.execution_offset, value.execution_fingerprint.digest);
98 put64(output, layout.semantic_frontier_offset, value.boundary.semantic_frontier);
99 putDigest(output, layout.block_root_offset, value.block_root.digest);
100 put64(output, layout.terminal_offset, value.boundary.terminal_offset);
101 put64(output, layout.settled_request_offset, value.settled.request_cursor);
102 put64(output, layout.event_consumed_offset, value.boundary.event_consumed);
103 put64(output, layout.event_produced_offset, value.boundary.event_produced);
104 output[layout.k0_offset] = value.k0.counter;
105 putDigest(output, layout.transcript_offset, value.semantic_transcript_digest);
106 }
107
108 fn encodeCpu(
109 value: owner.CpuState,
110 output: *[schema.header_bytes]u8,
111 ) void {
112 const layout = schema.CpuLayout;
113 put64(output, layout.rip_offset, value.rip);
114 put64(output, layout.rsp_offset, value.rsp);
115 put64(output, layout.rdi_offset, value.rdi);
116 put64(output, layout.rflags_offset, value.rflags);
117 put64(output, layout.cr0_offset, value.cr0);
118 put64(output, layout.cr3_offset, value.cr3);
119 put64(output, layout.cr4_offset, value.cr4);
120 put64(output, layout.efer_offset, value.efer);
121 put16(output, layout.code_selector_offset, value.code_selector);
122 put16(output, layout.data_selector_offset, value.data_selector);
123 }
124
125 fn encodeImmutable(
126 image: core.provenance.ImmutableImage,
127 output: *[schema.header_bytes]u8,
128 ) void {
129 const layout = schema.ImmutableLayout;
130 putDigest(output, layout.digest_offset, image.digest);
131 put32(output, layout.entry_offset, image.entry_offset);
132 put16(output, layout.load_count_offset, image.load_count);
133 put16(output, layout.load_bytes_offset, schema.load_bytes);
134 for (image.loads, 0..) |load, index| {
135 encodeLoad(output, layout.loads_offset + index * schema.load_bytes, load);
136 }
137 }
138
139 fn encodeLoad(
140 output: *[schema.header_bytes]u8,
141 start: usize,
142 load: core.provenance.ImmutableLoad,
143 ) void {
144 const layout = schema.LoadLayout;
145 put32(output, start + layout.source_offset, load.source_offset);
146 put32(output, start + layout.file_offset, load.file_bytes);
147 put32(output, start + layout.memory_offset, load.memory_bytes);
148 put32(output, start + layout.physical_offset, load.physical_offset);
149 put64(output, start + layout.virtual_offset, load.virtual_offset);
150 put32(output, start + layout.flags_offset, load.flags);
151 }
152
153 fn putDigest(
154 output: *[schema.header_bytes]u8,
155 offset: usize,
156 value: os.abi.Digest,
157 ) void {
158 @memcpy(output[offset..][0..schema.digest_bytes], &value);
159 }
160
161 fn put16(output: *[schema.header_bytes]u8, offset: usize, value: u16) void {
162 wire.write16(output[offset..][0..2], value);
163 }
164
165 fn put32(output: *[schema.header_bytes]u8, offset: usize, value: u32) void {
166 wire.write32(output[offset..][0..4], value);
167 }
168
169 fn put64(output: *[schema.header_bytes]u8, offset: usize, value: u64) void {
170 wire.write64(output[offset..][0..8], value);
171 }