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 }