Make machine configuration authoritative and restore native checkpoints exactly

This commit is contained in:
2026-09-18 09:09:41 +08:00
parent 6a69511276
commit 4a568f1f4c
94 changed files with 10882 additions and 301 deletions

View File

@@ -0,0 +1,55 @@
import { fnv1a64 } from "./replay.mjs";
function buildId(core) {
if (typeof core._sim_checkpoint_build_id !== "function") throw new Error("native_checkpoint_build_id_missing");
const pointer = core._sim_checkpoint_build_id();
const id = new TextDecoder().decode(core.HEAPU8.subarray(pointer, pointer + 64));
if (!/^[a-f0-9]{64}$/.test(id)) throw new Error("native_checkpoint_unversioned_build");
return id;
}
// Copy opaque native state with zero-filled blocks omitted. No arithmetic or
// state reconstruction occurs here; each C adapter owns its layout/validation.
export function exportNativeCheckpoint(core, prefix, owner = null) {
const length = core[`_${prefix}_checkpoint_size`]();
const pointer = core._malloc(length);
if (!pointer) throw new Error(`${prefix}_checkpoint_allocation`);
try {
const args = owner === null ? [pointer, length] : [owner, pointer, length];
const code = core[`_${prefix}_checkpoint_export`](...args);
if (code !== 0) throw new Error(`${prefix}_checkpoint_export_${code}`);
const bytes = core.HEAPU8.subarray(pointer, pointer + length), blocks = [];
for (let offset = 0; offset < length; offset += 256) {
const block = bytes.subarray(offset, Math.min(offset + 256, length));
if (block.some((value) => value !== 0)) blocks.push([offset, Array.from(block, (value) => value.toString(16).padStart(2, "0")).join("")]);
}
const value = { schema: "native-checkpoint.v1", component: prefix, build_id: buildId(core), byte_length: length, blocks };
return { ...value, state_hash: fnv1a64(value) };
} finally { core._free(pointer); }
}
export function validateNativeCheckpoint(core, prefix, value) {
if (value?.build_id !== buildId(core)) throw new Error(`${prefix}_checkpoint_build_mismatch`);
const length = core[`_${prefix}_checkpoint_size`]();
if (!value || value.schema !== "native-checkpoint.v1" || value.component !== prefix || value.byte_length !== length || !Array.isArray(value.blocks) || fnv1a64(Object.fromEntries(Object.entries(value).filter(([key]) => key !== "state_hash"))) !== value.state_hash) throw new Error(`${prefix}_checkpoint_invalid`);
const bytes = new Uint8Array(length); let end = 0;
for (const [offset, hex] of value.blocks) {
if (!Number.isSafeInteger(offset) || offset < end || typeof hex !== "string" || !/^(?:[0-9a-f]{2})+$/.test(hex) || offset + hex.length / 2 > length) throw new Error(`${prefix}_checkpoint_blocks`);
for (let index = 0; index < hex.length; index += 2) bytes[offset + index / 2] = Number.parseInt(hex.slice(index, index + 2), 16);
end = offset + hex.length / 2;
}
return bytes;
}
export function restoreNativeCheckpoint(core, prefix, value, owner = null) {
const bytes = validateNativeCheckpoint(core, prefix, value);
const length = bytes.length;
const pointer = core._malloc(length);
if (!pointer) throw new Error(`${prefix}_checkpoint_allocation`);
try {
core.HEAPU8.set(bytes, pointer);
const args = owner === null ? [pointer, length] : [owner, pointer, length];
const code = core[`_${prefix}_checkpoint_restore`](...args);
if (code !== 0) throw new Error(`${prefix}_checkpoint_restore_${code}`);
} finally { core._free(pointer); }
}