Preserve authenticated driver monitoring artifacts during builds

This commit is contained in:
firestar5683
2026-11-06 07:46:10 -06:00
parent a2c96c47d6
commit d64fb74c31
51 changed files with 133 additions and 8 deletions
Binary file not shown.
Binary file not shown.
+18 -6
View File
@@ -6,7 +6,7 @@ from SCons.Script import Action, Value
from openpilot.common.transformations.camera import _ar_ox_fisheye, _os_fisheye
from openpilot.common.transformations.model import MEDMODEL_INPUT_SIZE, DM_INPUT_SIZE
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
from tools.laptop_device_build.qcom_artifact_contract import import_artifact
from tools.laptop_device_build.qcom_artifact_contract import import_artifact, preserve_stock_artifact
Import('env', 'arch')
@@ -35,7 +35,11 @@ laptop_qcom_import = arch == 'comma_arm64' and os.getenv('COMMA_LAPTOP_CROSS_BUI
qcom_package = Dir('#.cache/qcom-artifact-package').abspath
def model_action(command):
def model_action(command, *, stock=False):
if arch == 'comma_arm64' and stock and not laptop_qcom_import:
def keep_stock(target, source, env):
preserve_stock_artifact(Path(str(target[0])))
return Action(keep_stock, " [STOCK MODEL VERIFY] $TARGET")
if not laptop_qcom_import:
return Action(command, " [ONNX] $TARGET")
@@ -47,8 +51,8 @@ def model_action(command):
return Action(do_import, " [QCOM IMPORT] $TARGET")
def warp_action(command):
return model_action(command) if laptop_qcom_import else command
def warp_action(command, *, stock=False):
return model_action(command, stock=stock) if laptop_qcom_import or stock else command
if arch == 'comma_arm64':
tg_flags = 'DEV=QCOM IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1'
@@ -72,8 +76,12 @@ def compile_model(onnx_path, pkl_path):
node = lenv.Command(
target_pkl_path,
tinygrad_files + [onnx_path, Value(cmd)],
model_action(cmd),
model_action(cmd, stock=True),
)
if arch == 'comma_arm64' and not laptop_qcom_import:
lenv.Precious(node)
lenv.NoClean(node)
lenv.AlwaysBuild(node)
if laptop_qcom_import:
lenv.AlwaysBuild(node)
@@ -98,6 +106,10 @@ for cam_w, cam_h in camera_configs:
cmd = (f'{tg_flags} {mac_brew_string} python3 "{compiler}/compile_warp.py" '
f'--frame {cam_w},{cam_h},{stride},{y_height},{uv_height},{frame_size} --warp-to {dm_w}x{dm_h} '
f'--layout luma --border-fill 16 --transform-device NPY --output {dm_pkl_path}')
node = lenv.Command(dm_pkl_path, tinygrad_files + warp_deps + [Value(cmd)], warp_action(cmd))
node = lenv.Command(dm_pkl_path, tinygrad_files + warp_deps + [Value(cmd)], warp_action(cmd, stock=True))
if arch == 'comma_arm64' and not laptop_qcom_import:
lenv.Precious(node)
lenv.NoClean(node)
lenv.AlwaysBuild(node)
if laptop_qcom_import:
lenv.AlwaysBuild(node)
Binary file not shown.
@@ -99,6 +99,15 @@ def test_supported_backend_retains_models_and_camera_warp_graph(graph, monkeypat
# Token checks retain every required flag without requiring adjacent assignments.
for call in calls:
target, dependencies, command = call.args
if callable(command):
assert arch == "comma_arm64"
assert Path(target).name in {"dmonitoring_model_tinygrad.pkl", "dm_warp_1344x760_tinygrad.pkl", "dm_warp_1928x1208_tinygrad.pkl"}
owner = Mock()
monkeypatch.setitem(command.__globals__, "preserve_stock_artifact", owner)
command([target], [], env)
owner.assert_called_once_with(Path(target))
assert dependencies[-1].startswith(backend)
continue
tokens = shlex.split(command)
assert set(shlex.split(backend)) <= set(tokens)
assert str(compiler_root / "examples/openpilot" / ("compile_onnx.py" if target.endswith("dmonitoring_model_tinygrad.pkl")
@@ -149,3 +158,15 @@ def test_build_does_not_probe_chestnut_or_regenerate_shipped_big_artifacts(graph
assert not any(Path(call.args[0]).name.startswith("big_driving_") for call in env.Command.call_args_list)
env.SideEffect.assert_not_called()
env.Execute.assert_not_called()
def test_device_monitoring_nodes_never_recompile_pinned_artifacts(graph):
evaluate, env, _ = graph
evaluate("comma_arm64")
stock = [call for call in env.Command.call_args_list if Path(call.args[0]).name.startswith(("dm_warp_", "dmonitoring_model_"))]
assert len(stock) == 3
assert env.Precious.call_count == 3
assert env.NoClean.call_count == 3
assert env.AlwaysBuild.call_count == 3
assert all(callable(call.args[2]) for call in stock)
assert all(isinstance(call.args[2], str) for call in env.Command.call_args_list if Path(call.args[0]).name.startswith("driving_warp_"))
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
extern const uint8_t gitversion[29];
const uint8_t gitversion[29] = "DEV-63137021-Pf38f504f-DEBUG";
const uint8_t gitversion[29] = "DEV-a2c96c47-Pf38f504f-DEBUG";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
DEV-63137021-Pf38f504f-DEBUG
DEV-a2c96c47-Pf38f504f-DEBUG
View File
+1
View File
@@ -0,0 +1 @@
{"protected_inventory_sha256": "b5d40f93a0f42e051c568f7318f0ed742ef41f9c2c3af7df5edb47bcc76d0336", "schema_version": 1}
@@ -0,0 +1,67 @@
from pathlib import Path
from openpilot.common.file_chunker import materialize_file_chunked, package_file
import shutil
import pytest
from openpilot.starpilot.models.runtime_bridge import runtime
from tools.laptop_device_build import qcom_artifact_contract as contract
from tools.laptop_device_build import validate_artifacts as validator
ROOT = Path(__file__).resolve().parents[3]
MODELS = ROOT / "openpilot/selfdrive/modeld/models"
NAMES = ("dm_warp_1344x760_tinygrad.pkl", "dm_warp_1928x1208_tinygrad.pkl")
@pytest.mark.parametrize("name", NAMES)
def test_actual_shipped_warps_pass_the_startup_guard(name):
assert runtime._stock_bytes(MODELS / name) == (MODELS / name).read_bytes()
@pytest.mark.parametrize("name", NAMES)
def test_structural_pickle_validation_is_not_sufficient(name, tmp_path):
artifact = tmp_path / name
artifact.write_bytes((MODELS / name).read_bytes() + b"\0")
validator.require_qcom_pickle(artifact)
with pytest.raises(ValueError, match="Stock model artifact changed"):
runtime._stock_bytes(artifact)
with pytest.raises(ValueError, match="Stock model artifact changed"):
contract.preserve_stock_artifact(artifact)
@pytest.mark.parametrize("name", NAMES)
def test_device_build_preserves_verified_bytes_and_rejects_symlink(name, tmp_path):
artifact = tmp_path / name
shutil.copy2(MODELS / name, artifact)
before = artifact.stat()
contract.preserve_stock_artifact(artifact)
after = artifact.stat()
assert (before.st_ino, before.st_mtime_ns, before.st_size) == (after.st_ino, after.st_mtime_ns, after.st_size)
artifact.unlink()
artifact.symlink_to(MODELS / name)
with pytest.raises(OSError):
contract.preserve_stock_artifact(artifact)
def test_release_checks_all_three_actual_stock_artifacts():
validator.require_stock_monitoring(MODELS)
@pytest.mark.parametrize("name", NAMES)
def test_release_refuses_structurally_valid_but_untrusted_warp(name, tmp_path):
for other in (*NAMES, "dmonitoring_model_tinygrad.pkl"):
shutil.copy2(materialize_file_chunked(MODELS / other), tmp_path / other)
artifact = tmp_path / name
artifact.write_bytes(artifact.read_bytes() + b"\0")
with pytest.raises(ValueError, match="Stock model artifact changed"):
validator.require_stock_monitoring(tmp_path)
def test_chunked_monitoring_model_is_preserved_as_a_regular_build_target(tmp_path):
source = materialize_file_chunked(MODELS / "dmonitoring_model_tinygrad.pkl")
target = tmp_path / source.name.removesuffix(".unchunked")
package_file(source, target)
assert not target.exists()
contract.preserve_stock_artifact(target)
assert runtime._stock_bytes(target) == runtime._stock_bytes(source)
@@ -352,6 +352,23 @@ def import_artifact(package: Path, root: Path, target: Path, command: str) -> No
temporary.unlink(missing_ok=True)
def preserve_stock_artifact(target: Path) -> None:
from openpilot.common.file_chunker import materialize_file_chunked
from openpilot.starpilot.models.runtime_bridge.runtime import _stock_bytes
data = _stock_bytes(materialize_file_chunked(target))
if target.exists():
return
fd, temporary = tempfile.mkstemp(prefix=f'.{target.name}.', dir=target.parent)
try:
with os.fdopen(fd, 'wb') as output:
output.write(data)
output.flush()
os.fsync(output.fileno())
os.replace(temporary, target)
finally:
Path(temporary).unlink(missing_ok=True)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("command", choices=("source-signature", "record"))
@@ -195,6 +195,12 @@ def require_qcom_pickle(path: Path) -> None:
raise ValueError(f"{path}: missing TinyJit capture structure")
def require_stock_monitoring(model_dir: Path) -> None:
from openpilot.starpilot.models.runtime_bridge.runtime import _stock_bytes
for name in MODELS + tuple(f"dm_warp_{size}_tinygrad.pkl" for size in WARP_SIZES):
_stock_bytes(materialize_file_chunked(model_dir / name))
def validate(root: Path) -> None:
from tools.laptop_device_build.validate_flm_native import validate as validate_flm_native
validate_flm_native(root)
@@ -210,6 +216,7 @@ def validate(root: Path) -> None:
actual_warps.update(p.name for p in model_dir.glob("dm_warp_*_tinygrad.pkl"))
if actual_warps != set(WARPS):
raise ValueError(f"camera warp set differs from current camera configs: {sorted(actual_warps)}")
require_stock_monitoring(model_dir)
for name in (*MODELS, *WARPS):
require_qcom_pickle(model_dir / name)
shipped = materialize_file_chunked(model_dir / f"{DEFAULT_SMALL}_driving_tinygrad.pkl", DEFAULT_SMALL_SHA256)