lib/machine/src/checkpoint/roots/test.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

   1 const admission = @import("../../admission/root.zig");
   2 const checkpoint = @import("../root.zig");
   3 const core = @import("machine_instance_core");
   4 const fixture = @import("../../instance/fixture/root.zig").fixture;
   5 const instance = @import("../../instance/root.zig");
   6 const os = @import("os");
   7 const profile = @import("../../profile/root.zig");
   8 const std = @import("std");
   9 
  10 const roots = checkpoint.roots;
  11 const k0_elf = @embedFile("machine-k0-elf");
  12 const k0_manifest = @embedFile("machine-k0-manifest");
  13 
  14 const Entry = struct {
  15     kind: roots.ObjectKind,
  16     digest: os.abi.Digest,
  17     offset: u32,
  18     length: u32,
  19     marked: bool,
  20 };
  21 
  22 const Hidden = struct {
  23     kind: roots.ObjectKind,
  24     digest: os.abi.Digest,
  25 };
  26 
  27 const CrashCut = enum(u8) {
  28     after_begin,
  29     after_manifest_put,
  30     after_staged_read,
  31     before_commit,
  32     after_commit,
  33 };
  34 
  35 const TestStore = struct {
  36     entries: []Entry,
  37     bytes: []u8,
  38     lookup: []u32,
  39     entry_limit: u32,
  40     byte_limit: u64,
  41     committed_entries: u32 = 0,
  42     committed_bytes: u64 = 0,
  43     staged_entries: u32 = 0,
  44     staged_bytes: u64 = 0,
  45     root_count: u8 = 0,
  46     root_storage: [roots.chain_limit + 4]roots.ManifestRoot = undefined,
  47     root_seed_masks: [roots.chain_limit + 4]u8 = @splat(0),
  48     blocks: [roots.chain_limit + 4]os.abi.BlockRoot = undefined,
  49     block_marked: [roots.chain_limit + 4]bool = @splat(false),
  50     block_count: u8 = 0,
  51     block_verifications: u32 = 0,
  52     put_calls: u32 = 0,
  53     retain_calls: u32 = 0,
  54     collection_commits: u16 = 0,
  55     active: bool = false,
  56     collection_active: bool = false,
  57     collection_snapshot: roots.maintenance.CollectionSnapshot = undefined,
  58     block_available: bool = true,
  59     forge_page: bool = false,
  60     forged: bool = false,
  61     hidden: ?Hidden = null,
  62     crash_cut: ?CrashCut = null,
  63 
  64     fn init(entries: []Entry, bytes: []u8, lookup: []u32) TestStore {
  65         std.debug.assert(lookup.len != 0);
  66         std.debug.assert((lookup.len & (lookup.len - 1)) == 0);
  67         std.debug.assert(entries.len <= lookup.len / 2);
  68         @memset(lookup, 0);
  69         return .{
  70             .entries = entries,
  71             .bytes = bytes,
  72             .lookup = lookup,
  73             .entry_limit = @intCast(entries.len),
  74             .byte_limit = bytes.len,
  75         };
  76     }
  77 
  78     fn reset(self: *TestStore) void {
  79         self.committed_entries = 0;
  80         self.committed_bytes = 0;
  81         self.staged_entries = 0;
  82         self.staged_bytes = 0;
  83         self.root_count = 0;
  84         self.block_count = 0;
  85         self.block_verifications = 0;
  86         self.put_calls = 0;
  87         self.retain_calls = 0;
  88         self.collection_commits = 0;
  89         self.active = false;
  90         self.collection_active = false;
  91         self.block_available = true;
  92         self.forge_page = false;
  93         self.forged = false;
  94         self.hidden = null;
  95         self.crash_cut = null;
  96         self.entry_limit = @intCast(self.entries.len);
  97         self.byte_limit = self.bytes.len;
  98         @memset(self.lookup, 0);
  99         @memset(&self.root_seed_masks, 0);
 100         @memset(&self.block_marked, false);
 101     }
 102 
 103     fn restart(self: *TestStore) TestStore {
 104         const committed_entries = self.committed_entries;
 105         const committed_bytes = self.committed_bytes;
 106         const root_count = self.root_count;
 107         const block_count = self.block_count;
 108         var roots_copy: [roots.chain_limit + 4]roots.ManifestRoot = undefined;
 109         var seeds_copy: [roots.chain_limit + 4]u8 = @splat(0);
 110         var blocks_copy: [roots.chain_limit + 4]os.abi.BlockRoot = undefined;
 111         @memcpy(roots_copy[0..root_count], self.root_storage[0..root_count]);
 112         @memcpy(seeds_copy[0..root_count], self.root_seed_masks[0..root_count]);
 113         @memcpy(blocks_copy[0..block_count], self.blocks[0..block_count]);
 114         var result = TestStore.init(self.entries, self.bytes, self.lookup);
 115         result.committed_entries = committed_entries;
 116         result.committed_bytes = committed_bytes;
 117         result.staged_entries = committed_entries;
 118         result.staged_bytes = committed_bytes;
 119         result.root_count = root_count;
 120         result.block_count = block_count;
 121         @memcpy(result.root_storage[0..root_count], roots_copy[0..root_count]);
 122         @memcpy(result.root_seed_masks[0..root_count], seeds_copy[0..root_count]);
 123         @memcpy(result.blocks[0..block_count], blocks_copy[0..block_count]);
 124         for (result.entries[0..committed_entries]) |*entry| entry.marked = false;
 125         result.rebuildLookup();
 126         return result;
 127     }
 128 
 129     fn storage(self: *TestStore) roots.Storage {
 130         return .{ .context = self, .vtable = &vtable };
 131     }
 132 
 133     const vtable: roots.Storage.VTable = .{
 134         .begin = begin,
 135         .put = put,
 136         .read_staged = readStaged,
 137         .commit = commit,
 138         .abort = abort,
 139         .read = read,
 140         .verify_block = verifyBlock,
 141         .begin_collection = beginCollection,
 142         .read_seed = readSeed,
 143         .retain_object = retainObject,
 144         .retain_block = retainBlock,
 145         .commit_collection = commitCollection,
 146         .abort_collection = abortCollection,
 147     };
 148 
 149     fn begin(context: *anyopaque, capacity: roots.Capacity) roots.StorageError!void {
 150         const self = from(context);
 151         if (self.active or self.collection_active) {
 152             return error.RootTransactionInUse;
 153         }
 154         if (capacity.objects > self.entry_limit or capacity.bytes > self.byte_limit) {
 155             return error.RootCapacityExceeded;
 156         }
 157         self.staged_entries = self.committed_entries;
 158         self.staged_bytes = self.committed_bytes;
 159         self.active = true;
 160         if (self.takeCrash(.after_begin)) return error.RootWriteFailed;
 161     }
 162 
 163     fn put(
 164         context: *anyopaque,
 165         kind: roots.ObjectKind,
 166         digest: os.abi.Digest,
 167         content: []const u8,
 168     ) roots.StorageError!void {
 169         const self = from(context);
 170         if (!self.active) return error.RootWriteFailed;
 171         self.put_calls += 1;
 172         if (self.find(kind, digest, self.staged_entries)) |entry| {
 173             if (!std.mem.eql(u8, self.entryBytes(entry), content)) {
 174                 return error.RootCollision;
 175             }
 176             return;
 177         }
 178         const next_bytes = std.math.add(u64, self.staged_bytes, content.len) catch
 179             return error.RootCapacityExceeded;
 180         if (self.staged_entries >= self.entry_limit or next_bytes > self.byte_limit) {
 181             return error.RootCapacityExceeded;
 182         }
 183         const offset: usize = @intCast(self.staged_bytes);
 184         @memcpy(self.bytes[offset..][0..content.len], content);
 185         const entry_index = self.staged_entries;
 186         self.entries[entry_index] = .{
 187             .kind = kind,
 188             .digest = digest,
 189             .offset = @intCast(offset),
 190             .length = @intCast(content.len),
 191             .marked = false,
 192         };
 193         try self.indexEntry(entry_index);
 194         self.staged_entries += 1;
 195         self.staged_bytes = next_bytes;
 196         if (self.forge_page and !self.forged and kind == .page) {
 197             self.bytes[offset] ^= 1;
 198             self.forged = true;
 199         }
 200         if (kind == .manifest and self.takeCrash(.after_manifest_put)) {
 201             return error.RootWriteFailed;
 202         }
 203     }
 204 
 205     fn readStaged(
 206         context: *anyopaque,
 207         kind: roots.ObjectKind,
 208         digest: os.abi.Digest,
 209         output: []u8,
 210     ) roots.StorageError!void {
 211         const self = from(context);
 212         if (!self.active) return error.RootReadFailed;
 213         try self.copy(kind, digest, self.staged_entries, output);
 214         if (kind == .manifest and self.takeCrash(.after_staged_read)) {
 215             return error.RootReadFailed;
 216         }
 217     }
 218 
 219     fn commit(
 220         context: *anyopaque,
 221         root: roots.ManifestRoot,
 222     ) roots.StorageError!void {
 223         const self = from(context);
 224         if (self.takeCrash(.before_commit)) return error.RootWriteFailed;
 225         if (!self.active or self.find(.manifest, root.digest, self.staged_entries) == null) {
 226             return error.RootWriteFailed;
 227         }
 228         if (!self.hasRoot(root)) {
 229             if (self.root_count == self.root_storage.len) {
 230                 return error.RootCapacityExceeded;
 231             }
 232             self.root_storage[self.root_count] = root;
 233             self.root_seed_masks[self.root_count] = 0;
 234             self.root_count += 1;
 235         }
 236         self.committed_entries = self.staged_entries;
 237         self.committed_bytes = self.staged_bytes;
 238         self.active = false;
 239         if (self.takeCrash(.after_commit)) return error.RootWriteFailed;
 240     }
 241 
 242     fn abort(context: *anyopaque) void {
 243         const self = from(context);
 244         if (!self.active) return;
 245         self.staged_entries = self.committed_entries;
 246         self.staged_bytes = self.committed_bytes;
 247         self.active = false;
 248         self.rebuildLookup();
 249     }
 250 
 251     fn read(
 252         context: *anyopaque,
 253         kind: roots.ObjectKind,
 254         digest: os.abi.Digest,
 255         output: []u8,
 256     ) roots.StorageError!void {
 257         const self = from(context);
 258         return self.copy(kind, digest, self.committed_entries, output);
 259     }
 260 
 261     fn verifyBlock(
 262         context: *anyopaque,
 263         block: os.abi.BlockRoot,
 264     ) roots.StorageError!void {
 265         const self = from(context);
 266         self.block_verifications += 1;
 267         if (!self.block_available) return error.RootReadFailed;
 268         if (block.generation == 0) return error.RootReadFailed;
 269         os.abi.wire.validateDigest(block.digest) catch return error.RootReadFailed;
 270         if (self.blockIndex(block) == null) {
 271             if (self.collection_active) return error.RootMissing;
 272             if (self.block_count == self.blocks.len) {
 273                 return error.RootCapacityExceeded;
 274             }
 275             self.blocks[self.block_count] = block;
 276             self.block_marked[self.block_count] = false;
 277             self.block_count += 1;
 278         }
 279     }
 280 
 281     fn beginCollection(
 282         context: *anyopaque,
 283         capacity: roots.maintenance.CollectionCapacity,
 284     ) roots.StorageError!roots.maintenance.CollectionSnapshot {
 285         const self = from(context);
 286         if (self.active or self.collection_active) {
 287             return error.RootTransactionInUse;
 288         }
 289         const snapshot = self.collectionSnapshot();
 290         if (!snapshotFits(capacity.limits, snapshot)) {
 291             return error.RootCollectionCapacityExceeded;
 292         }
 293         self.clearCollectionMarks();
 294         self.collection_snapshot = snapshot;
 295         self.collection_active = true;
 296         return snapshot;
 297     }
 298 
 299     fn readSeed(
 300         context: *anyopaque,
 301         class: roots.maintenance.ReachabilityClass,
 302         expected_index: u16,
 303     ) roots.StorageError!roots.ManifestRoot {
 304         const self = from(context);
 305         if (!self.collection_active) return error.RootCollectionFailed;
 306         var index: u16 = 0;
 307         for (self.root_storage[0..self.root_count], 0..) |root, root_index| {
 308             if (self.root_seed_masks[root_index] & classMask(class) == 0) continue;
 309             if (index == expected_index) return root;
 310             index += 1;
 311         }
 312         return error.RootSeedMissing;
 313     }
 314 
 315     fn retainObject(
 316         context: *anyopaque,
 317         kind: roots.ObjectKind,
 318         digest: os.abi.Digest,
 319     ) roots.StorageError!roots.maintenance.Retention {
 320         const self = from(context);
 321         if (!self.collection_active) return error.RootCollectionFailed;
 322         if (self.hidden) |hidden| {
 323             if (kind == hidden.kind and std.mem.eql(u8, &digest, &hidden.digest)) {
 324                 return error.RootMissing;
 325             }
 326         }
 327         const index = self.findIndex(kind, digest, self.committed_entries) orelse
 328             return error.RootMissing;
 329         self.retain_calls += 1;
 330         if (self.entries[index].marked) return .existing;
 331         self.entries[index].marked = true;
 332         return .fresh;
 333     }
 334 
 335     fn retainBlock(
 336         context: *anyopaque,
 337         block: os.abi.BlockRoot,
 338     ) roots.StorageError!roots.maintenance.Retention {
 339         const self = from(context);
 340         if (!self.collection_active) return error.RootCollectionFailed;
 341         const index = self.blockIndex(block) orelse return error.RootMissing;
 342         self.retain_calls += 1;
 343         if (self.block_marked[index]) return .existing;
 344         self.block_marked[index] = true;
 345         return .fresh;
 346     }
 347 
 348     fn commitCollection(
 349         context: *anyopaque,
 350     ) roots.StorageError!roots.maintenance.CollectionReport {
 351         const self = from(context);
 352         if (!self.collection_active) return error.RootCollectionFailed;
 353         const snapshot = self.collection_snapshot;
 354         const retained_objects = self.compactObjects();
 355         const retained_roots = self.compactRoots();
 356         const retained_blocks = self.compactBlocks();
 357         self.collection_active = false;
 358         self.collection_commits += 1;
 359         return .{
 360             .retained_roots = retained_roots,
 361             .collected_roots = snapshot.roots - retained_roots,
 362             .retained_objects = retained_objects,
 363             .collected_objects = snapshot.objects - retained_objects,
 364             .retained_blocks = retained_blocks,
 365             .collected_blocks = snapshot.blocks - retained_blocks,
 366         };
 367     }
 368 
 369     fn abortCollection(context: *anyopaque) void {
 370         const self = from(context);
 371         if (!self.collection_active) return;
 372         self.clearCollectionMarks();
 373         self.collection_active = false;
 374     }
 375 
 376     fn seedRoot(
 377         self: *TestStore,
 378         class: roots.maintenance.ReachabilityClass,
 379         root: roots.ManifestRoot,
 380     ) roots.StorageError!void {
 381         if (self.active or self.collection_active) {
 382             return error.RootTransactionInUse;
 383         }
 384         const index = self.rootIndex(root) orelse return error.RootSeedMissing;
 385         self.root_seed_masks[index] |= classMask(class);
 386     }
 387 
 388     fn collectionSnapshot(
 389         self: *const TestStore,
 390     ) roots.maintenance.CollectionSnapshot {
 391         return .{
 392             .seeds = self.seedCounts(),
 393             .roots = self.root_count,
 394             .objects = self.committed_entries,
 395             .blocks = self.block_count,
 396         };
 397     }
 398 
 399     fn seedCounts(self: *const TestStore) roots.maintenance.SeedCounts {
 400         var counts: roots.maintenance.SeedCounts = .{
 401             .chic_worlds = 0,
 402             .live_staged_instances = 0,
 403             .retained_receipts = 0,
 404             .concurrent_readers = 0,
 405         };
 406         for (self.root_seed_masks[0..self.root_count]) |mask| {
 407             if (mask & classMask(.chic_world) != 0) counts.chic_worlds += 1;
 408             if (mask & classMask(.live_staged_instance) != 0) {
 409                 counts.live_staged_instances += 1;
 410             }
 411             if (mask & classMask(.retained_receipt) != 0) {
 412                 counts.retained_receipts += 1;
 413             }
 414             if (mask & classMask(.concurrent_reader) != 0) {
 415                 counts.concurrent_readers += 1;
 416             }
 417         }
 418         return counts;
 419     }
 420 
 421     fn compactObjects(self: *TestStore) u32 {
 422         var retained: u32 = 0;
 423         var retained_bytes: u64 = 0;
 424         for (self.entries[0..self.committed_entries]) |entry| {
 425             if (!entry.marked) continue;
 426             const length: usize = entry.length;
 427             const source: usize = entry.offset;
 428             const destination: usize = @intCast(retained_bytes);
 429             if (source != destination) {
 430                 std.mem.copyForwards(
 431                     u8,
 432                     self.bytes[destination..][0..length],
 433                     self.bytes[source..][0..length],
 434                 );
 435             }
 436             self.entries[retained] = .{
 437                 .kind = entry.kind,
 438                 .digest = entry.digest,
 439                 .offset = @intCast(destination),
 440                 .length = entry.length,
 441                 .marked = false,
 442             };
 443             retained += 1;
 444             retained_bytes += entry.length;
 445         }
 446         self.committed_entries = retained;
 447         self.committed_bytes = retained_bytes;
 448         self.staged_entries = retained;
 449         self.staged_bytes = retained_bytes;
 450         self.rebuildLookup();
 451         return retained;
 452     }
 453 
 454     fn compactRoots(self: *TestStore) u16 {
 455         const original = self.root_count;
 456         var retained: u8 = 0;
 457         for (self.root_storage[0..original], 0..) |root, index| {
 458             if (self.find(.manifest, root.digest, self.committed_entries) == null) {
 459                 continue;
 460             }
 461             self.root_storage[retained] = root;
 462             self.root_seed_masks[retained] = self.root_seed_masks[index];
 463             retained += 1;
 464         }
 465         @memset(self.root_seed_masks[retained..original], 0);
 466         self.root_count = retained;
 467         return retained;
 468     }
 469 
 470     fn compactBlocks(self: *TestStore) u16 {
 471         const original = self.block_count;
 472         var retained: u8 = 0;
 473         for (self.blocks[0..original], 0..) |block, index| {
 474             if (!self.block_marked[index]) continue;
 475             self.blocks[retained] = block;
 476             self.block_marked[retained] = false;
 477             retained += 1;
 478         }
 479         @memset(self.block_marked[retained..original], false);
 480         self.block_count = retained;
 481         return retained;
 482     }
 483 
 484     fn clearCollectionMarks(self: *TestStore) void {
 485         for (self.entries[0..self.committed_entries]) |*entry| {
 486             entry.marked = false;
 487         }
 488         @memset(self.block_marked[0..self.block_count], false);
 489     }
 490 
 491     fn blockIndex(
 492         self: *const TestStore,
 493         block: os.abi.BlockRoot,
 494     ) ?u8 {
 495         for (self.blocks[0..self.block_count], 0..) |existing, index| {
 496             if (std.meta.eql(existing, block)) return @intCast(index);
 497         }
 498         return null;
 499     }
 500 
 501     fn rootIndex(
 502         self: *const TestStore,
 503         root: roots.ManifestRoot,
 504     ) ?u8 {
 505         for (self.root_storage[0..self.root_count], 0..) |existing, index| {
 506             if (std.meta.eql(existing, root)) return @intCast(index);
 507         }
 508         return null;
 509     }
 510 
 511     fn takeCrash(self: *TestStore, cut: CrashCut) bool {
 512         if (self.crash_cut != cut) return false;
 513         self.crash_cut = null;
 514         return true;
 515     }
 516 
 517     fn snapshotFits(
 518         limits: roots.maintenance.CollectionLimits,
 519         snapshot: roots.maintenance.CollectionSnapshot,
 520     ) bool {
 521         inline for (.{
 522             roots.maintenance.ReachabilityClass.chic_world,
 523             roots.maintenance.ReachabilityClass.live_staged_instance,
 524             roots.maintenance.ReachabilityClass.retained_receipt,
 525             roots.maintenance.ReachabilityClass.concurrent_reader,
 526         }) |class| {
 527             if (snapshot.seeds.count(class) > limits.seeds.count(class)) {
 528                 return false;
 529             }
 530         }
 531         return snapshot.roots <= limits.roots and
 532             snapshot.objects <= limits.objects and
 533             snapshot.blocks <= limits.blocks;
 534     }
 535 
 536     fn classMask(class: roots.maintenance.ReachabilityClass) u8 {
 537         const shift: u3 = @intCast(@backingInt(class));
 538         return @as(u8, 1) << shift;
 539     }
 540 
 541     fn copy(
 542         self: *TestStore,
 543         kind: roots.ObjectKind,
 544         digest: os.abi.Digest,
 545         count: u32,
 546         output: []u8,
 547     ) roots.StorageError!void {
 548         if (self.hidden) |hidden| {
 549             if (kind == hidden.kind and std.mem.eql(u8, &digest, &hidden.digest)) {
 550                 return error.RootMissing;
 551             }
 552         }
 553         const entry = self.find(kind, digest, count) orelse
 554             return error.RootMissing;
 555         const content = self.entryBytes(entry);
 556         if (content.len != output.len) return error.RootReadFailed;
 557         @memcpy(output, content);
 558     }
 559 
 560     fn find(
 561         self: *const TestStore,
 562         kind: roots.ObjectKind,
 563         digest: os.abi.Digest,
 564         count: u32,
 565     ) ?Entry {
 566         const index = self.findIndex(kind, digest, count) orelse return null;
 567         return self.entries[index];
 568     }
 569 
 570     fn findIndex(
 571         self: *const TestStore,
 572         kind: roots.ObjectKind,
 573         digest: os.abi.Digest,
 574         count: u32,
 575     ) ?u32 {
 576         var slot = self.lookupSlot(kind, digest);
 577         for (0..self.lookup.len) |_| {
 578             const encoded_index = self.lookup[slot];
 579             if (encoded_index == 0) return null;
 580             const entry_index = encoded_index - 1;
 581             if (entry_index < count) {
 582                 const entry = self.entries[entry_index];
 583                 if (entry.kind == kind and
 584                     std.mem.eql(u8, &entry.digest, &digest)) return entry_index;
 585             }
 586             slot = (slot + 1) & (self.lookup.len - 1);
 587         }
 588         return null;
 589     }
 590 
 591     fn indexEntry(self: *TestStore, entry_index: u32) roots.StorageError!void {
 592         const entry = self.entries[entry_index];
 593         var slot = self.lookupSlot(entry.kind, entry.digest);
 594         for (0..self.lookup.len) |_| {
 595             if (self.lookup[slot] == 0) {
 596                 self.lookup[slot] = entry_index + 1;
 597                 return;
 598             }
 599             slot = (slot + 1) & (self.lookup.len - 1);
 600         }
 601         return error.RootCapacityExceeded;
 602     }
 603 
 604     fn rebuildLookup(self: *TestStore) void {
 605         @memset(self.lookup, 0);
 606         for (0..self.committed_entries) |entry_index| {
 607             self.indexEntry(@intCast(entry_index)) catch unreachable;
 608         }
 609     }
 610 
 611     fn lookupSlot(
 612         self: *const TestStore,
 613         kind: roots.ObjectKind,
 614         digest: os.abi.Digest,
 615     ) usize {
 616         var hash: u64 = 14_695_981_039_346_656_037;
 617         hash = (hash ^ @backingInt(kind)) *% 1_099_511_628_211;
 618         for (digest) |byte| {
 619             hash = (hash ^ byte) *% 1_099_511_628_211;
 620         }
 621         return @intCast(hash & @as(u64, @intCast(self.lookup.len - 1)));
 622     }
 623 
 624     fn entryBytes(self: *const TestStore, entry: Entry) []const u8 {
 625         const offset: usize = entry.offset;
 626         return self.bytes[offset..][0..entry.length];
 627     }
 628 
 629     fn hasRoot(self: *const TestStore, root: roots.ManifestRoot) bool {
 630         for (self.root_storage[0..self.root_count]) |existing| {
 631             if (std.meta.eql(existing, root)) return true;
 632         }
 633         return false;
 634     }
 635 
 636     fn firstEntry(self: *const TestStore, kind: roots.ObjectKind) Entry {
 637         for (self.entries[0..self.committed_entries]) |entry| {
 638             if (entry.kind == kind) return entry;
 639         }
 640         unreachable;
 641     }
 642 
 643     fn lastEntrySince(
 644         self: *const TestStore,
 645         kind: roots.ObjectKind,
 646         first: u32,
 647     ) Entry {
 648         var index = self.committed_entries;
 649         while (index > first) {
 650             index -= 1;
 651             const entry = self.entries[index];
 652             if (entry.kind == kind) return entry;
 653         }
 654         unreachable;
 655     }
 656 
 657     fn from(context: *anyopaque) *TestStore {
 658         return @ptrCast(@alignCast(context));
 659     }
 660 };
 661 
 662 const delta_extra_objects: usize = 256;
 663 const delta_extra_bytes: usize = 1024 * 1024;
 664 var entry_storage: [roots.publication_capacity.objects + delta_extra_objects]Entry =
 665     undefined;
 666 var object_bytes: [roots.publication_capacity.bytes + delta_extra_bytes]u8 =
 667     undefined;
 668 var lookup_storage: [131_072]u32 = undefined;
 669 var published_ram: [checkpoint.ram_bytes]u8 align(checkpoint.ram_alignment) = undefined;
 670 var reopened_ram: [checkpoint.ram_bytes]u8 align(checkpoint.ram_alignment) = undefined;
 671 const delta_page_limit: usize = 64;
 672 const DeltaPageStorage = [delta_page_limit * checkpoint.hot.page_bytes]u8;
 673 var delta_indices: [delta_page_limit]u16 = undefined;
 674 var delta_pages: DeltaPageStorage align(checkpoint.hot.page_bytes) = undefined;
 675 const branch_page_limit: usize = 128;
 676 const BranchPageStorage = [branch_page_limit * roots.page_bytes]u8;
 677 var first_branch_indices: [branch_page_limit]u16 = undefined;
 678 var first_branch_pages: BranchPageStorage align(roots.page_bytes) = undefined;
 679 var first_branch_authenticated: [roots.branch.authentication_word_count]u64 = undefined;
 680 var first_branch_digests: [roots.page_count]os.abi.Digest = undefined;
 681 var second_branch_indices: [branch_page_limit]u16 = undefined;
 682 var second_branch_pages: BranchPageStorage align(roots.page_bytes) = undefined;
 683 var second_branch_authenticated: [roots.branch.authentication_word_count]u64 = undefined;
 684 var second_branch_digests: [roots.page_count]os.abi.Digest = undefined;
 685 
 686 const DeltaWitness = struct {
 687     parent: roots.Binding,
 688     first_delta: roots.Binding,
 689     full: roots.Binding,
 690     root: roots.ManifestRoot,
 691     manifest: roots.Manifest,
 692     missing: Entry,
 693 };
 694 
 695 test "immutable roots deduplicate, isolate pages, and reject unsafe publication" {
 696     var checkpoint_storage = checkpoint.Storage.init();
 697     const captured = try capture(&checkpoint_storage, &published_ram);
 698     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 699     const injected = store.storage();
 700 
 701     const first = try expectOneDeduplicatedRoot(&store, injected, &captured);
 702     try expectReopenedRootOwnsBytes(&store, injected, first);
 703     try expectEveryReopenDigestVerified(&store, injected, first.root);
 704     try expectForgedDigestRejected(&store, &captured);
 705     try expectCapacityRejectedBeforeWrites(&store, &captured);
 706 }
 707 
 708 test "dirty delta roots match full capture and reopen after restart" {
 709     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 710     const witness = try publishDeltaChain(&store);
 711     @memset(&published_ram, 0xa1);
 712     @memset(&reopened_ram, 0xa2);
 713     @memset(&delta_indices, 0);
 714     @memset(&delta_pages, 0xa3);
 715 
 716     var restarted = store.restart();
 717     const reopened = try roots.reopen(restarted.storage(), witness.root);
 718     try std.testing.expectEqualDeep(witness.manifest, reopened);
 719     try std.testing.expectEqual(@as(u32, 2), restarted.block_verifications);
 720 
 721     restarted.hidden = .{
 722         .kind = witness.missing.kind,
 723         .digest = witness.missing.digest,
 724     };
 725     try std.testing.expectError(
 726         error.RootMissing,
 727         roots.reopen(restarted.storage(), witness.root),
 728     );
 729 }
 730 
 731 test "compacted checkpoint chain preserves bytes and machine digest" {
 732     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 733     const witness = try publishDeltaChain(&store);
 734     const compacted = try roots.maintenance.compact(
 735         store.storage(),
 736         witness.root,
 737     );
 738     const old = try roots.materialize(
 739         store.storage(),
 740         witness.root,
 741         &published_ram,
 742     );
 743     const new = try roots.materialize(
 744         store.storage(),
 745         compacted.root,
 746         &reopened_ram,
 747     );
 748     try std.testing.expect(old.parent != null);
 749     try std.testing.expect(new.parent == null);
 750     try std.testing.expect(!std.meta.eql(witness.root, compacted.root));
 751     try std.testing.expectEqualDeep(old.machine, new.machine);
 752     try std.testing.expectEqualDeep(old.memory, new.memory);
 753     try std.testing.expectEqualDeep(old.pages, new.pages);
 754     try std.testing.expectEqualSlices(u8, &published_ram, &reopened_ram);
 755 }
 756 
 757 test "collection retains every root class and removes an orphan" {
 758     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 759     const witness = try publishDeltaChain(&store);
 760     const compacted = try roots.maintenance.compact(
 761         store.storage(),
 762         witness.root,
 763     );
 764     var reader = try restoreFirstBranch(&store, witness.first_delta.root, 0);
 765     try store.seedRoot(.chic_world, compacted.root);
 766     try store.seedRoot(.live_staged_instance, witness.full.root);
 767     try store.seedRoot(.retained_receipt, witness.parent.root);
 768     try store.seedRoot(.concurrent_reader, reader.root);
 769     const capacity = try exactCollectionCapacity(&store);
 770     const report = try roots.maintenance.collect(store.storage(), capacity);
 771     try std.testing.expect(capacity.metadata_bytes >= capacity.limits.objects);
 772     try std.testing.expect(@as(u64, store.retain_calls) <= capacity.work);
 773     try std.testing.expect(report.collected_roots > 0);
 774     try std.testing.expect(report.collected_objects > 0);
 775     _ = try roots.reopen(store.storage(), compacted.root);
 776     _ = try roots.reopen(store.storage(), witness.full.root);
 777     _ = try roots.reopen(store.storage(), witness.parent.root);
 778     var byte: [1]u8 = undefined;
 779     try reader.read(0, &byte);
 780     try std.testing.expectError(
 781         error.RootMissing,
 782         roots.reopen(store.storage(), witness.root),
 783     );
 784 }
 785 
 786 test "collection capacity refuses before classification" {
 787     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 788     const witness = try publishDeltaChain(&store);
 789     try store.seedRoot(.chic_world, witness.root);
 790     const before = store.collectionSnapshot();
 791     var limits = collectionLimits(before);
 792     limits.objects -= 1;
 793     const capacity = try roots.maintenance.CollectionCapacity.derive(limits);
 794     try std.testing.expectError(
 795         error.RootCollectionCapacityExceeded,
 796         roots.maintenance.collect(store.storage(), capacity),
 797     );
 798     try std.testing.expectEqual(@as(u32, 0), store.retain_calls);
 799     try std.testing.expectEqual(@as(u16, 0), store.collection_commits);
 800     try std.testing.expectEqualDeep(before, store.collectionSnapshot());
 801     _ = try roots.reopen(store.storage(), witness.root);
 802 }
 803 
 804 test "compaction crash cuts expose only complete roots" {
 805     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 806     const witness = try publishDeltaChain(&store);
 807     const entries = store.committed_entries;
 808     const bytes = store.committed_bytes;
 809     const root_count = store.root_count;
 810     const cuts = [_]CrashCut{
 811         .after_begin,
 812         .after_manifest_put,
 813         .after_staged_read,
 814         .before_commit,
 815         .after_commit,
 816     };
 817     for (cuts) |cut| {
 818         restoreCrashBaseline(&store, entries, bytes, root_count);
 819         store.crash_cut = cut;
 820         try expectCompactionCrash(&store, witness.root, cut);
 821         var restarted = store.restart();
 822         try expectCompletePublishedRoots(&restarted);
 823         _ = try roots.reopen(restarted.storage(), witness.root);
 824         if (cut == .after_commit) {
 825             try std.testing.expectEqual(root_count + 1, restarted.root_count);
 826             const compacted = restarted.root_storage[root_count];
 827             const value = try roots.reopen(restarted.storage(), compacted);
 828             try std.testing.expect(value.parent == null);
 829             try std.testing.expectEqualDeep(witness.manifest.machine, value.machine);
 830         } else {
 831             try std.testing.expectEqual(root_count, restarted.root_count);
 832         }
 833     }
 834 }
 835 
 836 test "shared root branch untouched residency is metadata only" {
 837     var checkpoint_storage = checkpoint.Storage.init();
 838     const captured = try capture(&checkpoint_storage, &published_ram);
 839     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 840     const binding = try roots.bind(store.storage(), &captured);
 841     const committed_bytes = store.committed_bytes;
 842     const put_calls = store.put_calls;
 843     const branch = try restoreFirstBranch(&store, binding.root, 0);
 844     try expectUntouchedBranchResidentBound(&branch);
 845     try std.testing.expectEqual(committed_bytes, store.committed_bytes);
 846     try std.testing.expectEqual(put_calls, store.put_calls);
 847 }
 848 
 849 test "shared root branches authenticate lazily and isolate private writes" {
 850     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 851     const witness = try publishDeltaChain(&store);
 852     var first = try restoreFirstBranch(&store, witness.root, branch_page_limit);
 853     var second = try restoreSecondBranch(&store, witness.root, branch_page_limit);
 854     try expectUntouchedBranchResidentBound(&first);
 855 
 856     const address = checkpoint.ram_bytes - roots.page_bytes;
 857     var original: [1]u8 = undefined;
 858     try first.read(address, &original);
 859     try second.read(address, &original);
 860     const committed_bytes = store.committed_bytes;
 861     const put_calls = store.put_calls;
 862     try first.write(address, &.{0xa1});
 863     try expectBranchByte(&first, address, 0xa1);
 864     try expectBranchByte(&second, address, original[0]);
 865     try second.write(address, &.{0xb2});
 866     try expectBranchByte(&first, address, 0xa1);
 867     try expectBranchByte(&second, address, 0xb2);
 868     try std.testing.expectEqual(@as(u16, 1), first.privatePageCount());
 869     try std.testing.expectEqual(@as(u16, 1), second.privatePageCount());
 870     try std.testing.expectEqual(committed_bytes, store.committed_bytes);
 871     try std.testing.expectEqual(put_calls, store.put_calls);
 872 }
 873 
 874 test "shared root branch rejects sabotage at first page touch" {
 875     var checkpoint_storage = checkpoint.Storage.init();
 876     const captured = try capture(&checkpoint_storage, &published_ram);
 877     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 878     const binding = try roots.bind(store.storage(), &captured);
 879     var branch = try restoreFirstBranch(&store, binding.root, 1);
 880     const page = store.firstEntry(.page);
 881     store.bytes[page.offset] ^= 1;
 882     var byte: [1]u8 = undefined;
 883     try std.testing.expectError(error.RootObjectCorrupt, branch.read(0, &byte));
 884     store.bytes[page.offset] ^= 1;
 885     try branch.read(0, &byte);
 886     try std.testing.expectEqual(published_ram[0], byte[0]);
 887 }
 888 
 889 test "shared root branch pool exhaustion refuses before writes" {
 890     var checkpoint_storage = checkpoint.Storage.init();
 891     const captured = try capture(&checkpoint_storage, &published_ram);
 892     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 893     const binding = try roots.bind(store.storage(), &captured);
 894     var branch = try restoreFirstBranch(&store, binding.root, 1);
 895     const address = roots.page_bytes - 1;
 896     var before: [2]u8 = undefined;
 897     try branch.read(address, &before);
 898     try std.testing.expectError(
 899         error.BranchPageCapacityExceeded,
 900         branch.write(address, &.{ 0x91, 0x92 }),
 901     );
 902     try std.testing.expectEqual(@as(u16, 0), branch.privatePageCount());
 903     var after: [2]u8 = undefined;
 904     try branch.read(address, &after);
 905     try std.testing.expectEqualSlices(u8, &before, &after);
 906 }
 907 
 908 test "instances restore shared roots and keep branch writes private" {
 909     var store = TestStore.init(&entry_storage, &object_bytes, &lookup_storage);
 910     const witness = try publishDeltaChain(&store);
 911     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 912     const selected = input(execution);
 913     const restore_input: instance.SharedRestoreInput = .{
 914         .expected_root = witness.root,
 915         .profile = selected.profile,
 916         .execution_manifest = k0_manifest,
 917         .fence = selected.fence,
 918     };
 919     var first_owner = instance.Storage.init();
 920     var second_owner = instance.Storage.init();
 921     var first = try expectSharedInstance(
 922         &first_owner,
 923         store.storage(),
 924         try firstBranchStorage(branch_page_limit),
 925         restore_input,
 926     );
 927     defer first.deinit();
 928     var second = try expectSharedInstance(
 929         &second_owner,
 930         store.storage(),
 931         try secondBranchStorage(branch_page_limit),
 932         restore_input,
 933     );
 934     defer second.deinit();
 935 
 936     try std.testing.expectEqual(@as(usize, 0), first.ram.len);
 937     try std.testing.expectEqual(
 938         @as(u16, @intCast(core.layout.reactivation_page_count)),
 939         try first.privatePageCount(),
 940     );
 941     try std.testing.expect(
 942         try first.residentMemoryBytes() < checkpoint.ram_bytes / 16,
 943     );
 944     const ready = try first.run();
 945     try std.testing.expectEqual(
 946         os.abi.channel.DoorbellCode.ready,
 947         ready.doorbell.code,
 948     );
 949     var activation: instance.EventBatch = undefined;
 950     try first.takeEvents(&activation);
 951     const address = checkpoint.ram_bytes - roots.page_bytes;
 952     var original: [1]u8 = undefined;
 953     try first.readMemory(address, &original);
 954     const committed_bytes = store.committed_bytes;
 955     const put_calls = store.put_calls;
 956     try first.writeMemory(address, &.{0xa1});
 957     try expectInstanceByte(&first, address, 0xa1);
 958     try expectInstanceByte(&second, address, original[0]);
 959     try second.writeMemory(address, &.{0xb2});
 960     try expectInstanceByte(&first, address, 0xa1);
 961     try expectInstanceByte(&second, address, 0xb2);
 962     try std.testing.expectEqual(committed_bytes, store.committed_bytes);
 963     try std.testing.expectEqual(put_calls, store.put_calls);
 964 
 965     first.deinit();
 966     @memset(&first_branch_pages, 0xa5);
 967     var exhausted_owner = instance.Storage.init();
 968     const exhausted = instance.Instance.restoreShared(
 969         &exhausted_owner,
 970         store.storage(),
 971         try firstBranchStorage(core.layout.reactivation_page_count - 1),
 972         restore_input,
 973     );
 974     switch (exhausted) {
 975         .rejected => |failure| try std.testing.expectEqual(
 976             error.MemoryCapacityExceeded,
 977             failure,
 978         ),
 979         .ready, .unavailable => return error.ExpectedCapacityRefusal,
 980     }
 981     try std.testing.expect(std.mem.allEqual(
 982         u8,
 983         first_branch_pages[0 .. (core.layout.reactivation_page_count - 1) * roots.page_bytes],
 984         0xa5,
 985     ));
 986 }
 987 
 988 test "immutable root publication capacity rejects max plus one" {
 989     var page_limits = roots.publication_limits;
 990     page_limits.pages += 1;
 991     try std.testing.expectError(
 992         error.PageCapacityExceeded,
 993         roots.Capacity.derive(page_limits),
 994     );
 995     var node_limits = roots.publication_limits;
 996     node_limits.nodes += 1;
 997     try std.testing.expectError(
 998         error.NodeCapacityExceeded,
 999         roots.Capacity.derive(node_limits),
1000     );
1001     var manifest_limits = roots.publication_limits;
1002     manifest_limits.manifests += 1;
1003     try std.testing.expectError(
1004         error.ManifestCapacityExceeded,
1005         roots.Capacity.derive(manifest_limits),
1006     );
1007 }
1008 
1009 fn exactCollectionCapacity(
1010     store: *const TestStore,
1011 ) !roots.maintenance.CollectionCapacity {
1012     return roots.maintenance.CollectionCapacity.derive(
1013         collectionLimits(store.collectionSnapshot()),
1014     );
1015 }
1016 
1017 fn collectionLimits(
1018     snapshot: roots.maintenance.CollectionSnapshot,
1019 ) roots.maintenance.CollectionLimits {
1020     return .{
1021         .seeds = snapshot.seeds,
1022         .roots = snapshot.roots,
1023         .objects = snapshot.objects,
1024         .blocks = snapshot.blocks,
1025     };
1026 }
1027 
1028 fn restoreCrashBaseline(
1029     store: *TestStore,
1030     entries: u32,
1031     bytes: u64,
1032     root_count: u8,
1033 ) void {
1034     store.committed_entries = entries;
1035     store.committed_bytes = bytes;
1036     store.staged_entries = entries;
1037     store.staged_bytes = bytes;
1038     store.root_count = root_count;
1039     store.active = false;
1040     store.collection_active = false;
1041     store.crash_cut = null;
1042     store.rebuildLookup();
1043 }
1044 
1045 fn expectCompactionCrash(
1046     store: *TestStore,
1047     root: roots.ManifestRoot,
1048     cut: CrashCut,
1049 ) !void {
1050     switch (cut) {
1051         .after_staged_read => try std.testing.expectError(
1052             error.RootReadFailed,
1053             roots.maintenance.compact(store.storage(), root),
1054         ),
1055         else => try std.testing.expectError(
1056             error.RootWriteFailed,
1057             roots.maintenance.compact(store.storage(), root),
1058         ),
1059     }
1060 }
1061 
1062 fn expectCompletePublishedRoots(store: *TestStore) !void {
1063     for (store.root_storage[0..store.root_count]) |root| {
1064         _ = try roots.reopen(store.storage(), root);
1065     }
1066 }
1067 
1068 fn publishDeltaChain(store: *TestStore) !DeltaWitness {
1069     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
1070     const selected = input(execution);
1071     var live_storage = instance.Storage.init();
1072     var machine = switch (instance.Instance.init(
1073         &live_storage,
1074         &fixture.ram,
1075         selected,
1076     )) {
1077         .ready => |value| value,
1078         .unavailable => return error.UnexpectedBackendUnavailable,
1079         .rejected => |failure| return failure,
1080     };
1081     defer machine.deinit();
1082     try driveToReceipt(&machine, selected.fence, 0);
1083 
1084     var parent_storage = checkpoint.Storage.init();
1085     const parent = try machine.captureCheckpoint(&parent_storage, &published_ram);
1086     const parent_binding = try roots.bind(store.storage(), &parent);
1087     dirtyLastPages(&machine, 2, 0x41);
1088     const hot_storage = try checkpoint.hot.Storage.init(
1089         &delta_indices,
1090         &delta_pages,
1091     );
1092     const first_snapshot = try machine.captureHot(&parent, hot_storage);
1093     try std.testing.expectEqual(@as(u16, 2), first_snapshot.dirtyPageCount());
1094     try std.testing.expectEqualDeep(
1095         parent_binding.manifest.block,
1096         first_snapshot.material.receipt.block_root,
1097     );
1098     try expectDeltaCapacityRejected(store, parent_binding.root, &first_snapshot);
1099     const first_put = store.put_calls;
1100     const first_block_verifications = store.block_verifications;
1101     const first_delta = try roots.bindDelta(
1102         store.storage(),
1103         parent_binding.root,
1104         &first_snapshot,
1105     );
1106     try std.testing.expectEqual(@as(u32, 19), store.put_calls - first_put);
1107     try std.testing.expectEqual(
1108         first_block_verifications,
1109         store.block_verifications,
1110     );
1111 
1112     var full_storage = checkpoint.Storage.init();
1113     const full = try machine.captureCheckpoint(&full_storage, &reopened_ram);
1114     const full_binding = try roots.bind(store.storage(), &full);
1115     try expectSameMachine(first_delta, full_binding);
1116     return publishNextDelta(
1117         store,
1118         &machine,
1119         parent_binding,
1120         first_delta,
1121         full_binding,
1122         &full,
1123         hot_storage,
1124         selected.fence,
1125     );
1126 }
1127 
1128 fn restoreFirstBranch(
1129     store: *TestStore,
1130     root: roots.ManifestRoot,
1131     pages: usize,
1132 ) !roots.branch.Branch {
1133     return roots.branch.restore(
1134         store.storage(),
1135         root,
1136         try firstBranchStorage(pages),
1137     );
1138 }
1139 
1140 fn firstBranchStorage(pages: usize) !roots.branch.Storage {
1141     return roots.branch.Storage.init(
1142         first_branch_indices[0..pages],
1143         first_branch_pages[0 .. pages * roots.page_bytes],
1144         &first_branch_authenticated,
1145         &first_branch_digests,
1146     );
1147 }
1148 
1149 fn restoreSecondBranch(
1150     store: *TestStore,
1151     root: roots.ManifestRoot,
1152     pages: usize,
1153 ) !roots.branch.Branch {
1154     return roots.branch.restore(
1155         store.storage(),
1156         root,
1157         try secondBranchStorage(pages),
1158     );
1159 }
1160 
1161 fn secondBranchStorage(pages: usize) !roots.branch.Storage {
1162     return roots.branch.Storage.init(
1163         second_branch_indices[0..pages],
1164         second_branch_pages[0 .. pages * roots.page_bytes],
1165         &second_branch_authenticated,
1166         &second_branch_digests,
1167     );
1168 }
1169 
1170 fn expectUntouchedBranchResidentBound(branch: *const roots.branch.Branch) !void {
1171     try std.testing.expectEqual(@as(u16, 0), branch.privatePageCount());
1172     try std.testing.expect(branch.residentBytes() < 4 * roots.page_bytes);
1173     try std.testing.expect(branch.residentBytes() * 1_024 < checkpoint.ram_bytes);
1174 }
1175 
1176 fn expectBranchByte(
1177     branch: *roots.branch.Branch,
1178     address: usize,
1179     expected: u8,
1180 ) !void {
1181     var actual: [1]u8 = undefined;
1182     try branch.read(address, &actual);
1183     try std.testing.expectEqual(expected, actual[0]);
1184 }
1185 
1186 fn expectSharedInstance(
1187     storage: *instance.Storage,
1188     root_storage: roots.Storage,
1189     branch_storage: roots.branch.Storage,
1190     input_value: instance.SharedRestoreInput,
1191 ) !instance.Instance {
1192     return switch (instance.Instance.restoreShared(
1193         storage,
1194         root_storage,
1195         branch_storage,
1196         input_value,
1197     )) {
1198         .ready => |value| value,
1199         .unavailable => error.UnexpectedBackendUnavailable,
1200         .rejected => |failure| failure,
1201     };
1202 }
1203 
1204 fn expectInstanceByte(
1205     machine: *const instance.Instance,
1206     address: usize,
1207     expected: u8,
1208 ) !void {
1209     var actual: [1]u8 = undefined;
1210     try machine.readMemory(address, &actual);
1211     try std.testing.expectEqual(expected, actual[0]);
1212 }
1213 
1214 fn publishNextDelta(
1215     store: *TestStore,
1216     machine: *instance.Instance,
1217     parent: roots.Binding,
1218     first_delta: roots.Binding,
1219     full_binding: roots.Binding,
1220     full: *const checkpoint.Checkpoint,
1221     hot_storage: checkpoint.hot.Storage,
1222     fence: os.abi.ActivationFence,
1223 ) !DeltaWitness {
1224     var next = fence;
1225     next.generation += 1;
1226     next.token = @splat(0x66);
1227     try machine.reactivate(next);
1228     try driveToReceipt(machine, next, os.k0.request_bytes.len);
1229     dirtyLastPages(machine, 3, 0x52);
1230     const second_snapshot = try machine.captureHot(full, hot_storage);
1231     try std.testing.expect(second_snapshot.dirtyPageCount() > 0);
1232     try std.testing.expect(!std.meta.eql(
1233         first_delta.manifest.block,
1234         second_snapshot.material.receipt.block_root,
1235     ));
1236     const before_entries = store.committed_entries;
1237     const block_verifications = store.block_verifications;
1238     const second_delta = try roots.bindDelta(
1239         store.storage(),
1240         first_delta.root,
1241         &second_snapshot,
1242     );
1243     try std.testing.expectEqual(
1244         block_verifications + 1,
1245         store.block_verifications,
1246     );
1247     return .{
1248         .parent = parent,
1249         .first_delta = first_delta,
1250         .full = full_binding,
1251         .root = second_delta.root,
1252         .manifest = second_delta.manifest,
1253         .missing = store.lastEntrySince(.page, before_entries),
1254     };
1255 }
1256 
1257 fn dirtyLastPages(machine: *instance.Instance, count: usize, byte: u8) void {
1258     std.debug.assert(count <= delta_page_limit);
1259     for (0..count) |offset| {
1260         const page_index = checkpoint.page_count - 1 - offset;
1261         machine.ram[page_index * checkpoint.ram_alignment] = byte + @as(
1262             u8,
1263             @intCast(offset),
1264         );
1265     }
1266 }
1267 
1268 fn expectDeltaCapacityRejected(
1269     store: *TestStore,
1270     parent: roots.ManifestRoot,
1271     snapshot: *const checkpoint.hot.Snapshot,
1272 ) !void {
1273     const entry_limit = store.entry_limit;
1274     const roots_before = store.root_count;
1275     const puts_before = store.put_calls;
1276     store.entry_limit = 0;
1277     defer store.entry_limit = entry_limit;
1278     try std.testing.expectError(
1279         error.RootCapacityExceeded,
1280         roots.bindDelta(store.storage(), parent, snapshot),
1281     );
1282     try std.testing.expectEqual(roots_before, store.root_count);
1283     try std.testing.expectEqual(puts_before, store.put_calls);
1284     try std.testing.expect(!store.active);
1285 }
1286 
1287 fn expectSameMachine(delta: roots.Binding, full: roots.Binding) !void {
1288     try std.testing.expectEqualDeep(delta.manifest.machine, full.manifest.machine);
1289     try std.testing.expectEqualDeep(delta.manifest.memory, full.manifest.memory);
1290     try std.testing.expectEqualDeep(delta.manifest.pages, full.manifest.pages);
1291     try std.testing.expect(delta.manifest.parent != null);
1292     try std.testing.expect(full.manifest.parent == null);
1293 }
1294 
1295 fn expectNothingPublished(store: *const TestStore) !void {
1296     try std.testing.expectEqual(@as(u32, 0), store.committed_entries);
1297     try std.testing.expectEqual(@as(u64, 0), store.committed_bytes);
1298     try std.testing.expectEqual(@as(u8, 0), store.root_count);
1299     try std.testing.expect(!store.active);
1300 }
1301 
1302 fn expectOneDeduplicatedRoot(
1303     store: *TestStore,
1304     storage: roots.Storage,
1305     captured: *const checkpoint.Checkpoint,
1306 ) !roots.Binding {
1307     const first = try roots.bind(storage, captured);
1308     const object_count = store.committed_entries;
1309     const stored_bytes = store.committed_bytes;
1310     const second = try roots.bind(storage, captured);
1311     try std.testing.expectEqualDeep(first, second);
1312     try std.testing.expectEqual(object_count, store.committed_entries);
1313     try std.testing.expectEqual(stored_bytes, store.committed_bytes);
1314     try std.testing.expectEqual(@as(u8, 1), store.root_count);
1315     return first;
1316 }
1317 
1318 fn expectReopenedRootOwnsBytes(
1319     store: *TestStore,
1320     storage: roots.Storage,
1321     first: roots.Binding,
1322 ) !void {
1323     const reopened = try roots.reopen(storage, first.root);
1324     try std.testing.expectEqualDeep(first.manifest, reopened);
1325     const changed_index = published_ram.len - 1;
1326     const original = published_ram[changed_index];
1327     published_ram[changed_index] ^= 1;
1328     const materialized = try roots.materialize(storage, first.root, &reopened_ram);
1329     try std.testing.expectEqualDeep(first.manifest, materialized);
1330     try std.testing.expectEqual(original, reopened_ram[changed_index]);
1331     try std.testing.expect(published_ram[changed_index] != reopened_ram[changed_index]);
1332     published_ram[changed_index] = original;
1333     try std.testing.expectEqual(@as(u32, 4), store.block_verifications);
1334 }
1335 
1336 fn expectEveryReopenDigestVerified(
1337     store: *TestStore,
1338     storage: roots.Storage,
1339     root: roots.ManifestRoot,
1340 ) !void {
1341     const page = store.firstEntry(.page);
1342     store.bytes[page.offset] ^= 1;
1343     try std.testing.expectError(error.RootObjectCorrupt, roots.reopen(storage, root));
1344     store.bytes[page.offset] ^= 1;
1345 
1346     const node = store.firstEntry(.node);
1347     store.bytes[node.offset] ^= 1;
1348     try std.testing.expectError(error.RootObjectCorrupt, roots.reopen(storage, root));
1349     store.bytes[node.offset] ^= 1;
1350 
1351     const manifest = store.firstEntry(.manifest);
1352     store.bytes[manifest.offset] ^= 1;
1353     try std.testing.expectError(error.ManifestRootMismatch, roots.reopen(storage, root));
1354     store.bytes[manifest.offset] ^= 1;
1355 
1356     store.block_available = false;
1357     try std.testing.expectError(error.RootReadFailed, roots.reopen(storage, root));
1358     store.block_available = true;
1359     try std.testing.expectEqual(@as(u32, 7), store.block_verifications);
1360 }
1361 
1362 fn expectForgedDigestRejected(
1363     store: *TestStore,
1364     captured: *const checkpoint.Checkpoint,
1365 ) !void {
1366     store.reset();
1367     store.forge_page = true;
1368     try std.testing.expectError(
1369         error.RootObjectCorrupt,
1370         roots.bind(store.storage(), captured),
1371     );
1372     try std.testing.expect(store.forged);
1373     try expectNothingPublished(store);
1374 }
1375 
1376 fn expectCapacityRejectedBeforeWrites(
1377     store: *TestStore,
1378     captured: *const checkpoint.Checkpoint,
1379 ) !void {
1380     store.reset();
1381     store.entry_limit = roots.publication_capacity.objects - 1;
1382     try std.testing.expectError(
1383         error.RootCapacityExceeded,
1384         roots.bind(store.storage(), captured),
1385     );
1386     try std.testing.expectEqual(@as(u32, 0), store.put_calls);
1387     try expectNothingPublished(store);
1388 }
1389 
1390 fn capture(
1391     storage: *checkpoint.Storage,
1392     destination: []align(checkpoint.ram_alignment) u8,
1393 ) !checkpoint.Checkpoint {
1394     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
1395     const selected = input(execution);
1396     var live_storage = instance.Storage.init();
1397     var machine = switch (instance.Instance.init(
1398         &live_storage,
1399         &fixture.ram,
1400         selected,
1401     )) {
1402         .ready => |value| value,
1403         .unavailable => return error.UnexpectedBackendUnavailable,
1404         .rejected => |failure| return failure,
1405     };
1406     defer machine.deinit();
1407     try driveToReceipt(&machine, selected.fence, 0);
1408     return machine.captureCheckpoint(storage, destination);
1409 }
1410 
1411 fn driveToReceipt(
1412     machine: *instance.Instance,
1413     fence: os.abi.ActivationFence,
1414     terminal_offset: u64,
1415 ) !void {
1416     const ready = try machine.run();
1417     try std.testing.expectEqual(os.abi.channel.DoorbellCode.ready, ready.doorbell.code);
1418     var events: instance.EventBatch = undefined;
1419     try machine.takeEvents(&events);
1420     const basis = try machine.admissionBasis();
1421     const admitted = try admission.prepare(
1422         basis,
1423         try admission.terminal(
1424             terminal_offset,
1425             os.k0.request_bytes,
1426         ),
1427     );
1428     const delivery = try admission.bindDelivery(admitted, @splat(0x88), fence);
1429     try machine.deliverAdmitted(&delivery);
1430     const quiescent = try machine.run();
1431     try std.testing.expectEqual(
1432         os.abi.channel.DoorbellCode.quiescent,
1433         quiescent.doorbell.code,
1434     );
1435     try machine.takeEvents(&events);
1436     try machine.acknowledge(delivery.receipt);
1437     _ = try machine.quiescenceReceipt();
1438 }
1439 
1440 fn input(execution: os.boot.kernel.manifest.View) instance.Input {
1441     return .{
1442         .profile = profile.interpretedContinuationTestV1(),
1443         .elf = k0_elf,
1444         .execution_manifest = k0_manifest,
1445         .expected_execution_fingerprint = execution.header.fingerprint,
1446         .fence = .{
1447             .world = @splat(0x44),
1448             .generation = 1,
1449             .token = @splat(0x55),
1450         },
1451         .initial_time_tick = 7,
1452         .entropy_generation = 1,
1453         .terminal_offset = 0,
1454         .effect_frontier = 0,
1455         .block_root = @splat(0x33),
1456         .source_root = @splat(0x77),
1457         .input_frontier = 0,
1458         .terminal_input_offset = 0,
1459         .outstanding_effect = null,
1460     };
1461 }