Files
StarPilot/openpilot/starpilot/flm/live_tracking_probe_process.py
2026-10-21 23:28:39 -05:00

587 lines
25 KiB
Python

"""One bounded numerical probe child; results never carry current permission."""
from dataclasses import fields
import hashlib
from openpilot.starpilot.flm.fit_process import FitProcess
VERSION = 'live-probe-numerical-job-v1'
MAX_PACKED = 3 * 1024 * 1024
def _digest(payload):
return hashlib.sha256(payload).hexdigest()
def _plain(value, cls):
from openpilot.starpilot.flm.live_tracking_probe import _record
_record(value, cls)
return {field.name: getattr(value, field.name) for field in fields(cls)}
def _literal_control(row):
from openpilot.starpilot.flm.fullrate_collector import ControlEvidence
from openpilot.starpilot.flm.live_tracking_probe import _primitive, _trace_key
if type(row) is not ControlEvidence:
raise ValueError('exact original control receipt required')
_trace_key(row.effect_trace)
result = {}
for field in fields(ControlEvidence):
value = getattr(row, field.name)
if field.name == 'effect_trace':
result[field.name] = _literal_trace(value)
else:
_primitive(value)
result[field.name] = value
return result
def _literal_trace(value):
from openpilot.starpilot.flm.live_tracking_probe import _primitive, _trace_key
_trace_key(value)
if value is None:
return None
trace = {item.name: getattr(value, item.name) for item in fields(type(value))}
trace['envelope'] = {item.name: getattr(value.envelope, item.name) for item in fields(type(value.envelope))}
_primitive(trace)
return trace
def probe_replay_snapshot(replay, prefix_controls, *, endpoint_output=None):
"""Copy one genuine bounded raw prefix, without blocks or recorder mutation.
This is a restricted numerical transport, never an original/native acceptance.
The child recomputes every actual controller and native chronology check.
"""
from itertools import islice
from collections import OrderedDict, deque
from openpilot.starpilot.flm.controller_replay import (
ControllerReplay,
SelectedControllerFactory,
Snapshot,
ReplayFrame,
pack_primitive_snapshot,
)
from openpilot.starpilot.flm.pid_controller_replay import PidControllerFactory
from openpilot.starpilot.flm.torque_emission_replay import EmissionHistory, Emission
from openpilot.starpilot.flm.torque_adapter import Objective
from openpilot.starpilot.flm.live_tracking_probe import _primitive, _factory_configuration, _projection_literal
from openpilot.starpilot.flm.learner_factory import _frame
from openpilot.starpilot.flm.original_context_receipts import _same_original_frame
from opendbc.car.steering_projection import TorqueProjection
if (
type(replay) is not ControllerReplay
or type(replay.emissions) is not EmissionHistory
or type(replay.factory) not in (SelectedControllerFactory, PidControllerFactory)
or type(prefix_controls) is not tuple
or not 1 <= len(prefix_controls) <= 100
):
raise ValueError('genuine bounded raw prefix owner required')
def source():
if (
type(replay.records) is not deque
or type(replay.checkpoints) is not deque
or type(replay.emissions.events) is not OrderedDict
or type(replay.emissions.carriers) is not OrderedDict
or type(replay.failed) is not bool
or type(replay.raw_mode) is not bool
):
raise ValueError('exact bounded recorder containers/flags required')
controls = tuple(_literal_control(row) for row in prefix_controls)
if any(type(row['control_ns']) is not int for row in controls):
raise ValueError('exact actual prefix clocks required')
first, last = controls[0]['control_ns'], controls[-1]['control_ns']
endpoint_apply_ns = None if endpoint_output is None else endpoint_output.apply_ns
if endpoint_output is not None and endpoint_output.control_ns != last:
raise ValueError('exact original endpoint application required')
if replay.failed or replay.raw_mode is not True or not 0 < first <= last <= first + 1_000_000_000:
raise ValueError('genuine bounded raw prefix unavailable')
candidates = []
for row in islice(reversed(replay.checkpoints), 600):
if type(row) is not tuple or len(row) != 2 or type(row[0]) is not int or row[0] <= 0 or type(row[1]) is not Snapshot:
raise ValueError('exact genuine checkpoint row required')
if row[0] <= last:
candidates.append(row)
latest = candidates[0] if candidates else None
if latest is None or latest[0] != first:
raise ValueError("latest genuine actual prefix checkpoint required")
checkpoint = latest[1]
if type(checkpoint) is not Snapshot or _primitive(checkpoint.values) != _primitive(prefix_controls[0].replay_snapshot):
raise ValueError('genuine actual prefix checkpoint required')
selected = []
# The endpoint can be up to2s old and its ORIGINAL checkpoint up to1s
# before it. Scan that already-retained context; the emitted job STILL
# contains at most100 original ticks and all old freshness guards remain.
for row in islice(reversed(replay.records), 301):
if type(row) is not ReplayFrame or type(row.control_ns) is not int:
raise ValueError('exact original prefix frame clock required')
if first <= row.control_ns <= last:
selected.append(row)
frames = tuple(reversed(selected))
stored = []
for frame in frames:
row = {field.name: _literal_trace(frame.effect_trace) if field.name == 'effect_trace' else getattr(frame, field.name) for field in fields(ReplayFrame)}
_primitive(row)
stored.append(row)
# The original comparator's unknown fallback may deepcopy. Only a fully
# closed literal frame graph may reach it, including all tuning fields.
if (
len(frames) != len(controls)
or not frames
or frames[0].control_ns != first
or frames[-1].control_ns != last
or any(not _same_original_frame(frame, _frame(control)) for frame, control in zip(frames, prefix_controls, strict=True))
):
raise ValueError('genuine complete original prefix differs')
selected_events = []
for event in islice(reversed(replay.emissions.events.values()), 301):
if type(event) is not Emission or type(event.control_ns) is not int:
raise ValueError('exact original native emission clock required')
if first <= event.control_ns <= last and (endpoint_apply_ns is None or event.apply_ns <= endpoint_apply_ns):
selected_events.append(event)
events = tuple(reversed(selected_events))
native = []
for event in events:
if type(event) is not Emission or type(event.witness) is not TorqueProjection:
raise ValueError('exact actual native prefix event required')
row = {field.name: _projection_literal(event.witness) if field.name == 'witness' else getattr(event, field.name) for field in fields(Emission)}
_primitive(row)
native.append(row)
if not events or events[-1].control_ns != last:
raise ValueError('actual endpoint native chronology missing')
first_frame, last_frame = events[0].witness.frame + 1, events[-1].witness.frame + 1
selected_carriers = []
for frame, row in islice(reversed(replay.emissions.carriers.items()), 301):
if type(frame) is not int or type(row) is not tuple or len(row) != 2 or any(type(value) is not int for value in row):
raise ValueError('exact actual native carrier row required')
if first_frame <= frame <= last_frame:
selected_carriers.append((frame, *row))
carriers = tuple(reversed(selected_carriers))
factory = replay.factory
mode, policy = _factory_configuration(factory)
from opendbc.car.car_helpers import interfaces
interface = interfaces.get(str(factory.cp.carFingerprint))
if type(factory) not in (SelectedControllerFactory, PidControllerFactory) or interface is None or factory.interface_class is not interface:
raise ValueError("exact registered prefix factory required")
constructor = (interface.__module__, interface.__qualname__, policy)
data = {
'version': 1,
'raw_mode': True,
'cp_bytes': factory.cp.as_builder().to_bytes(),
'mode': mode,
'turn_assist': factory.turn_assist,
'manual_baseline': factory.manual_baseline,
'manual_source_epoch': factory.manual_source_epoch,
'objective': _plain(replay.objective, Objective),
'identity': replay.identity,
'baseline_revision': replay.baseline_revision,
'model_revision': replay.model_revision,
'windows': ((first, last),),
'checkpoints': ((first, checkpoint.revision, checkpoint.values),),
'frames': tuple(stored),
'emissions': {'events': tuple(native), 'carriers': carriers},
}
# Includes genuine complete source receipts as well as transported raw data.
return data, _primitive((data, controls, constructor)), factory
data, key, factory = source()
packed = pack_primitive_snapshot(data)
if len(packed) > MAX_PACKED:
raise ValueError('bounded raw probe snapshot byte limit')
_, after, current_factory = source()
if after != key or current_factory is not factory:
raise ValueError('actual raw prefix source changed while copying')
return packed
def make_probe_job(
*,
replay_snapshot,
control,
output,
accepted_full30,
binding,
response_witness,
source,
evidence_ns,
queued_ns,
current_vehicle_model_anchor,
group,
names,
prefix_controls,
archived_clock=False,
):
"""Freeze genuine owner evidence, independently of later application authority.
evidence_ns is the ACTUAL parent observation time, never a fabricated emission
clock. Child wall time remains real; historical leases are checked at emission.
"""
from openpilot.starpilot.flm.controller_replay import pack_primitive_snapshot
from openpilot.starpilot.flm.fullrate_collector import AppliedEvidence
from openpilot.starpilot.flm.live_trial_contract import LiveTrialBinding, full_coordinates
from openpilot.starpilot.flm.live_tracking_response import witness_to_dict
from openpilot.starpilot.flm.live_tracking_probe import _primitive, _projection_literal
from openpilot.starpilot.flm.runtime_adapter_registry import SourceState
from opendbc.car.steering_projection import TorqueProjection
if (
type(archived_clock) is not bool
or type(evidence_ns) is not int
or evidence_ns <= 0
or type(queued_ns) is not int
or queued_ns <= 0
or not archived_clock
and evidence_ns > queued_ns
or type(replay_snapshot) is not bytes
or not 0 < len(replay_snapshot) <= MAX_PACKED
or type(prefix_controls) is not tuple
or not 1 <= len(prefix_controls) <= 100
or type(output) is not AppliedEvidence
or type(output.projection) is not TorqueProjection
):
raise ValueError('bounded genuine numerical probe evidence required')
binding.validate()
full_coordinates(accepted_full30, binding.baseline_revision)
applied = {
field.name: _projection_literal(output.projection) if field.name == 'projection' else getattr(output, field.name) for field in fields(AppliedEvidence)
}
_primitive(applied)
payload = {
'version': VERSION,
'replay': replay_snapshot,
'control': _literal_control(control),
'output': applied,
'accepted_full30': accepted_full30,
'binding': _plain(binding, LiveTrialBinding),
'witness': witness_to_dict(response_witness, now_ns=evidence_ns),
'source': _plain(source, SourceState),
'evidence_ns': evidence_ns,
'queued_ns': queued_ns,
'archived_clock': archived_clock,
'anchor': current_vehicle_model_anchor,
'group': group,
'names': names,
'prefix_controls': tuple(_literal_control(row) for row in prefix_controls),
}
_primitive(dict(payload, replay=None))
packed = pack_primitive_snapshot(payload)
if len(packed) > MAX_PACKED:
raise ValueError('numerical probe job byte bound')
return {'version': VERSION, 'payload': packed.hex(), 'sha256': _digest(packed)}
def decode_probe_job(job):
from openpilot.starpilot.flm.controller_replay import unpack_primitive_snapshot
from openpilot.starpilot.flm.live_tracking_probe import _primitive
if (
type(job) is not dict
or set(job) != {'version', 'payload', 'sha256'}
or job['version'] != VERSION
or type(job['payload']) is not str
or not 0 < len(job['payload']) <= 2 * MAX_PACKED
or type(job['sha256']) is not str
):
raise ValueError('restricted numerical probe envelope required')
packed = bytes.fromhex(job['payload'])
if _digest(packed) != job['sha256']:
raise ValueError('numerical job content changed')
payload = unpack_primitive_snapshot(packed)
if type(payload) is not dict or payload.get('version') != VERSION:
raise ValueError('numerical job schema differs')
batch = payload.get('batch')
if batch is not None:
if type(batch) is not tuple or not 1 <= len(batch) <= 4:
raise ValueError('bounded genuine numerical endpoint batch required')
_primitive(dict(payload, batch=None, replay=None))
rows = batch
else:
rows = (payload,)
for row in rows:
if (
type(row) is not dict
or row.get('version') != VERSION
or 'batch' in row
or type(row.get('replay')) is not bytes
or not 0 < len(row['replay']) <= MAX_PACKED
):
raise ValueError('bounded literal replay bytes required')
_primitive(dict(row, replay=None))
return payload
def make_probe_batch(jobs, *, queued_ns):
"""One child, up to four REAL independently anchored original endpoints.
Each original evidence clock and literal snapshot is retained. queued_ns is
only the actual batch lifecycle clock; no stale evidence becomes a grant.
"""
from openpilot.starpilot.flm.controller_replay import pack_primitive_snapshot
from openpilot.starpilot.flm.live_tracking_probe import _primitive
if type(jobs) is not tuple or not 1 <= len(jobs) <= 4 or type(queued_ns) is not int or queued_ns <= 0:
raise ValueError('bounded actual probe batch required')
rows = tuple(decode_probe_job(job) for job in jobs)
if any('batch' in row or type(row.get('prefix_controls')) is not tuple or not row['prefix_controls'] for row in rows):
raise ValueError("single genuine endpoint inputs required")
common = ('binding', 'accepted_full30', 'anchor', 'group', 'names', 'archived_clock')
first = rows[0]
previous = previous_apply = 0
from openpilot.starpilot.flm.controller_replay import MAX_FRAME_GAP_NS
for row in rows:
if (
'batch' in row
or any(_primitive(row[name]) != _primitive(first[name]) for name in common)
or type(row['control']['control_ns']) is not int
or not previous < row['control']['control_ns']
or not 0 < row['queued_ns'] <= queued_ns <= row['queued_ns'] + 2_000_000_000
):
raise ValueError('genuine same-checkpoint/profile/group probe batch required')
prefix = row['prefix_controls']
if any(type(item) is not dict for item in prefix) or type(row.get('control')) is not dict or type(row.get('output')) is not dict:
raise ValueError('exact original endpoint dictionaries required')
stamps = tuple(item.get('control_ns') for item in prefix)
apply_ns = row.get('output', {}).get('apply_ns')
if (
not 1 <= len(prefix) <= 100
or any(type(stamp) is not int for stamp in stamps)
or not 0 < stamps[0] <= stamps[-1] <= stamps[0] + 1_000_000_000
or any(not 0 < right - left <= MAX_FRAME_GAP_NS for left, right in zip(stamps, stamps[1:], strict=False))
or _primitive(prefix[-1]) != _primitive(row['control'])
or not prefix[0].get('replay_snapshot')
or any(item.get('replay_snapshot') for item in prefix[1:])
or type(apply_ns) is not int
or not previous_apply < apply_ns
):
raise ValueError('independent complete original prefix or application order differs')
previous = row['control']['control_ns']
previous_apply = apply_ns
payload = {'version': VERSION, 'queued_ns': queued_ns, 'batch': rows}
packed = pack_primitive_snapshot(payload)
if len(packed) > MAX_PACKED:
raise ValueError('numerical batch byte bound')
return {'version': VERSION, 'payload': packed.hex(), 'sha256': _digest(packed)}
def _prepared_context(data):
"""Small original request identity, independently recomputed by the worker."""
rows = data.get('batch', (data,))
return {
'batch': tuple(
{
'binding': row['binding'],
'control': {key: row['control'][key] for key in ('control_ns', 'stage_schema_revision')},
'output': {'apply_ns': row['output']['apply_ns']},
'accepted_full30': row['accepted_full30'],
'group': row['group'],
'names': row['names'],
'source': row['source'],
'anchor': row['anchor'],
'evidence_ns': row['evidence_ns'],
'queued_ns': row['queued_ns'],
'prefix_first_ns': row['prefix_controls'][0]['control_ns'],
'prefix_last_ns': row['prefix_controls'][-1]['control_ns'],
}
for row in rows
)
}
def _context_digest(context):
import json
raw = json.dumps(context, sort_keys=True, separators=(',', ':'), allow_nan=False).encode()
if not 0 < len(raw) <= 65536:
raise ValueError('bounded original numerical request context required')
return _digest(raw)
def original_probe_context(selected, accepted, binding, source, *, group, names, now_ns):
from dataclasses import asdict
rows = tuple(
{
'binding': asdict(binding),
'control': {'control_ns': control.control_ns, 'stage_schema_revision': control.stage_schema_revision},
'output': {'apply_ns': output.apply_ns},
'accepted_full30': accepted,
'group': group,
'names': names,
'source': asdict(source),
'anchor': control.vehicle_model_anchor,
'evidence_ns': now_ns,
'queued_ns': now_ns,
'prefix_controls': ({'control_ns': prefix[0].control_ns}, {'control_ns': prefix[-1].control_ns}),
}
for control, output, prefix in selected
)
context = _prepared_context({'batch': rows})
_context_digest(context)
return context
def prepare_probe_wire(jobs, *, queued_ns, expected):
"""Called in the preparation CHILD; never walk large replay graphs in parent."""
import json
job = make_probe_batch(tuple(jobs), queued_ns=queued_ns)
context = _prepared_context(decode_probe_job(job))
digest = _context_digest(context)
if digest != _context_digest(expected):
raise ValueError('prepared numerical input differs from original request')
wire = json.dumps(dict(job, preparedContextSha256=digest), separators=(',', ':'), allow_nan=False).encode()
from openpilot.starpilot.flm.fit_process import MAX_INPUT
if not 0 < len(wire) <= MAX_INPUT:
raise ValueError('prepared numerical IPC byte bound')
return {'wire': wire.decode('ascii'), 'wire_sha256': _digest(wire), 'job_sha256': job['sha256'], 'context_sha256': digest}
class ProbeProcess(FitProcess):
worker_module = 'openpilot.starpilot.flm.live_tracking_probe_worker'
wall_ns = 30_000_000_000
interval_ns = 0
def __init__(self, *, archived_diagnostic=False):
if type(archived_diagnostic) is not bool:
raise ValueError("explicit diagnostic clock mode required")
super().__init__()
self.expected = None
self.prepared_context_sha = None
self.archived_diagnostic = archived_diagnostic
def submit_probe(self, job, *, token, now_ns):
if self.child is not None:
return False
payload = decode_probe_job(job)
if not 0 < payload['queued_ns'] <= now_ns <= payload['queued_ns'] + 100_000_000:
return False
from openpilot.starpilot.flm.live_tracking_probe import _primitive, _evidence_clock
for row in payload.get('batch', (payload,)):
archived = row.get('archived_clock', False)
if archived and not self.archived_diagnostic:
return False
_evidence_clock(evidence_ns=row['evidence_ns'], queued_ns=row['queued_ns'], now_ns=now_ns, current_native=False, archived_clock=archived)
if not super().submit(job, token=(_primitive(token), self.archived_diagnostic, job['sha256']), now_ns=now_ns):
return False
# Independent immutable exact content; callers may mutate their original job.
self.expected = (job['sha256'], payload)
self.prepared_context_sha = None
return True
def submit_prepared_probe(self, prepared, *, expected, token, now_ns):
# Only immutable bytes and a small parent-owned original identity cross
# here. The worker recomputes this identity from its fully decoded job.
if self.child is not None:
return False
from openpilot.starpilot.flm.live_tracking_probe import _primitive
if type(prepared) is not dict or set(prepared) != {'wire', 'wire_sha256', 'job_sha256', 'context_sha256'}:
raise ValueError('prepared numerical envelope differs')
from openpilot.starpilot.flm.fit_process import MAX_INPUT
wire = prepared['wire']
if type(wire) is str:
if not 0 < len(wire) <= MAX_INPUT:
raise ValueError('prepared numerical wire bound')
try:
wire = wire.encode('ascii')
except UnicodeEncodeError as error:
raise ValueError('prepared numerical wire is not ASCII') from error
if (
type(wire) is not bytes
or not 0 < len(wire) <= MAX_INPUT
or _digest(wire) != prepared['wire_sha256']
or prepared['context_sha256'] != _context_digest(expected)
or type(prepared['job_sha256']) is not str
or len(prepared['job_sha256']) != 64
or any(char not in '0123456789abcdef' for char in prepared['job_sha256'])
):
raise ValueError('prepared numerical wire or original context differs')
rows = expected['batch']
if not 1 <= len(rows) <= 4 or any(not 0 < row['queued_ns'] <= now_ns <= row['queued_ns'] + 2_000_000_000 for row in rows):
return False
from copy import deepcopy
owned_context = deepcopy(expected)
digest = prepared['job_sha256']
if not super().submit_bytes(wire, token=(_primitive(token), self.archived_diagnostic, digest), now_ns=now_ns):
return False
self.expected = digest, owned_context
self.prepared_context_sha = prepared['context_sha256']
return True
def poll_probe(self, *, token, binding, now_ns):
expected = self.expected
prepared_sha = self.prepared_context_sha
from openpilot.starpilot.flm.live_tracking_probe import _primitive
digest = expected[0] if expected is not None else None
report = super().poll(token=(_primitive(token), self.archived_diagnostic, digest), now_ns=now_ns)
if self.child is None:
self.expected = None
self.prepared_context_sha = None
if report is None or expected is None:
return None
return self.decode_report(report, expected=expected, prepared_sha=prepared_sha, binding=binding)
@staticmethod
def decode_report(report, *, expected, prepared_sha, binding):
# Shared exact decoder for the existing numerical subprocess and the
# already-forked snapshot child. Neither result carries live permission.
from openpilot.starpilot.flm.live_tracking_probe import ProbeResult, ProbeCoordinate, _OWNER, _probe_key, validate_probe_result
from openpilot.starpilot.flm.live_trial_contract import LiveTrialBinding, full_coordinates
digest, payload = expected
batch = payload.get('batch')
key = 'results' if batch is not None else 'rows'
if (
type(report) is not dict
or set(report) != ({'version', 'sha256', key, 'contextSha256'} if prepared_sha else {'version', 'sha256', key})
or report['version'] != VERSION
or report['sha256'] != digest
or prepared_sha is not None
and report.get('contextSha256') != prepared_sha
):
raise ValueError('owned child numerical result/context differs')
def seal(data, output):
if (
LiveTrialBinding(**data['binding']) != binding
or type(output) is not list
or not 1 <= len(output) <= 30
or any(type(row) is not dict or set(row) != set(ProbeCoordinate.__dataclass_fields__) for row in output)
):
raise ValueError('owned child numerical result/context differs')
rows = tuple(ProbeCoordinate(**row) for row in output)
if tuple(row.name for row in rows) != data['names']:
raise ValueError('owned child coordinate group differs')
result = ProbeResult(
binding,
data['control']['control_ns'],
data['output']['apply_ns'],
full_coordinates(data['accepted_full30'], binding.baseline_revision),
binding.physical_model_revision,
rows,
'torque_pid' if data['control']['stage_schema_revision'] == 'pid-selected-stage-snapshot-v2' else 'torque',
data['group'],
None,
)
object.__setattr__(result, '_seal', (_OWNER, _probe_key(result)))
return validate_probe_result(result, binding)
if batch is not None:
if type(report['results']) is not list or len(report['results']) != len(batch):
raise ValueError('actual numerical endpoint batch shape differs')
return tuple(seal(data, output) for data, output in zip(batch, report['results'], strict=True))
return seal(payload, report['rows'])