mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
137 lines
7.7 KiB
Python
137 lines
7.7 KiB
Python
"""NEW event source feedback proof, separate from legacy event admission."""
|
|
from dataclasses import dataclass
|
|
from openpilot.starpilot.flm.candidate_feedback import LEGACY_POLICY,CLOSED_POLICY,PROOF_VERSION,policy as validate_candidate_policy
|
|
|
|
PROTOCOL='chronological-source-feedback-mean-fit-v1'
|
|
EVENT_VERSION=7
|
|
_SEAL=object()
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class FeedbackReplayEvidence:
|
|
binding: str
|
|
original: object
|
|
windows: tuple
|
|
engine_input_digest: str
|
|
_seal: object
|
|
candidate_policy: str = LEGACY_POLICY
|
|
|
|
|
|
def _inputs(engine, *, candidate_policy=LEGACY_POLICY):
|
|
# Hash trusted in-process objects ONLY; no pickle data is ever decoded here.
|
|
# Keep the same original CP/factory/controller/native/checkpoint/body coverage
|
|
# as the existing causal owned-input key, without recursively hashing this seal.
|
|
import hashlib
|
|
import pickle
|
|
from openpilot.starpilot.flm.controller_replay import SelectedControllerFactory
|
|
from openpilot.starpilot.flm.pid_controller_replay import PidControllerFactory
|
|
factory=engine.factory
|
|
if type(factory) not in (SelectedControllerFactory,PidControllerFactory):
|
|
raise ValueError('registered original feedback factory required')
|
|
policy=('torque',str(factory.policy)) if type(factory) is SelectedControllerFactory else ('stock-pid',None)
|
|
selected=(type(factory).__module__,type(factory).__qualname__,factory.cp.as_builder().to_bytes(),
|
|
str(factory.mode),policy,factory.turn_assist,factory.manual_baseline,factory.manual_source_epoch,
|
|
factory.interface_class.__module__,factory.interface_class.__qualname__)
|
|
native=(engine.emissions.cp.as_builder().to_bytes(),engine.emissions.identity,engine.emissions.baseline_revision,
|
|
tuple(engine.emissions.events.items()),tuple(engine.emissions.carriers.items()))
|
|
body=(engine.identity,engine.baseline_revision,engine.engine.model_revision,engine.engine.failed,
|
|
engine.engine.raw_mode,selected,engine.engine.objective,engine.objective,engine.reference,
|
|
engine.prior_full,engine.original_anchor,engine.activation_plan,engine.restore_envelope,
|
|
tuple(engine.records),tuple(engine.checkpoints),tuple(engine.replay_windows),native)
|
|
from openpilot.starpilot.flm.normalized_trace_archive import archive_key
|
|
if archive_key(engine) is not None:
|
|
body = (*body,archive_key(engine))
|
|
validate_candidate_policy(candidate_policy)
|
|
if candidate_policy != LEGACY_POLICY:
|
|
body = (*body,candidate_policy,PROOF_VERSION)
|
|
return hashlib.sha256(pickle.dumps(body,protocol=5)).hexdigest()
|
|
|
|
|
|
def verify_archive(packet, original):
|
|
from openpilot.starpilot.flm.feedback_archive import archive_binding
|
|
from openpilot.starpilot.flm.feedback_observation import verify_original
|
|
from openpilot.starpilot.flm.feedback_archive_codec import expand_observations
|
|
from openpilot.starpilot.flm.torque_raw_fit import output_from_dict
|
|
from openpilot.starpilot.flm.normalized_trace_archive import normalized_packet,archive_of
|
|
if normalized_packet(packet):
|
|
import pickle
|
|
owner_archive = archive_of(original)
|
|
if owner_archive is None or pickle.dumps(owner_archive.literal,protocol=5) != pickle.dumps(packet['trace_archive'],protocol=5):
|
|
raise ValueError('normalized feedback original literal source differs')
|
|
binding=archive_binding(packet)
|
|
publications,consumptions=expand_observations(packet['feedback_observations'],binding_digest=binding)
|
|
frames=tuple(original.records)
|
|
outputs={value.apply_ns:value for value in (output_from_dict(row) for row in packet['context_receipts']['outputs'])}
|
|
return verify_original(publications,consumptions,original.original_context_controls,outputs,original,binding,
|
|
expected_control_ids=tuple(frame.control_ns for frame in frames),context_packet=packet['context_receipts'],
|
|
frames=frames,allow_initial_context_only=True)
|
|
|
|
|
|
def attach_feedback_engine(engine, tape, *, candidate_policy=LEGACY_POLICY):
|
|
from openpilot.starpilot.flm.event_controller_replay import EventControllerReplay
|
|
from openpilot.starpilot.flm.feedback_observation import subset_verified
|
|
if type(engine) is not EventControllerReplay or engine.activation_plan is None:
|
|
raise ValueError('new feedback requires actual declared stage engine')
|
|
windows=[]
|
|
for bounds in engine.replay_windows:
|
|
controls=tuple(frame.control_ns for frame in engine.records if bounds[0]<=frame.control_ns<=bounds[1])
|
|
if not controls or controls[0]!=bounds[0] or controls[-1]!=bounds[1]:
|
|
raise ValueError('complete feedback engine window required')
|
|
context=tuple(row.control_ns for row in tape.context_only)
|
|
if context:
|
|
# The sealed global first q may precede a later stage-only replay.
|
|
if len(context) != 1 or context[0] > engine.records[0].control_ns:
|
|
raise ValueError('only original leading feedback context allowed')
|
|
controls=tuple(stamp for stamp in controls if stamp not in context)
|
|
subset=subset_verified(tape,controls,binding_digest=tape.binding_digest)
|
|
activation=engine.activation_plan.activation_for(*bounds)
|
|
if activation is None:
|
|
raise ValueError('original feedback activation clock required')
|
|
# An original context-only window has no treatment. Requiring every request
|
|
# to equal original through its end proves the unchanged prefix instead.
|
|
flag_activation=activation[0] or bounds[1]+1
|
|
windows.append((bounds,subset,flag_activation))
|
|
validate_candidate_policy(candidate_policy)
|
|
evidence=FeedbackReplayEvidence(tape.binding_digest,tape,tuple(windows),
|
|
_inputs(engine,candidate_policy=candidate_policy),_SEAL,candidate_policy)
|
|
engine.verified_feedback_tape=evidence
|
|
return evidence
|
|
|
|
|
|
def require_feedback_engine(engine):
|
|
from openpilot.starpilot.flm.feedback_observation import validate_subset_verified
|
|
evidence=getattr(engine,'verified_feedback_tape',None)
|
|
if (type(evidence) is not FeedbackReplayEvidence or evidence._seal is not _SEAL or
|
|
type(evidence.candidate_policy) is not str or evidence.candidate_policy not in (LEGACY_POLICY,CLOSED_POLICY) or
|
|
evidence.engine_input_digest!=_inputs(engine,candidate_policy=evidence.candidate_policy) or
|
|
tuple(bounds for bounds,_,_ in evidence.windows)!=tuple(engine.replay_windows)):
|
|
raise ValueError('owned original feedback engine evidence required')
|
|
for bounds,subset,activation in evidence.windows:
|
|
controls=tuple(frame.control_ns for frame in engine.records if bounds[0]<=frame.control_ns<=bounds[1] and
|
|
frame.control_ns not in tuple(row.control_ns for row in evidence.original.context_only))
|
|
# Validate the owner seal/digest and exact full window again, never trust an
|
|
# instance flag or wire-created VerifiedFeedbackTape-shaped object.
|
|
validate_subset_verified(subset,controls,binding_digest=evidence.binding)
|
|
if (engine.activation_plan.activation_for(*bounds)[0] or bounds[1]+1)!=activation:
|
|
raise ValueError('feedback activation changed')
|
|
return evidence
|
|
|
|
|
|
def verify_candidate_engine(engine,requests,reported):
|
|
from openpilot.starpilot.flm.feedback_observation import verify_candidate_flags
|
|
evidence=require_feedback_engine(engine)
|
|
if evidence.candidate_policy != LEGACY_POLICY:
|
|
raise ValueError('closed-loop candidate requires its own native chronology proof')
|
|
for _bounds,subset,activation in evidence.windows:
|
|
selected={row.consumption.control_ns:requests[row.consumption.control_ns] for row in subset.rows}
|
|
verify_candidate_flags(subset,selected,reported,activation_ns=activation,binding_digest=evidence.binding)
|
|
return True
|
|
|
|
|
|
def owned_feedback_key(engine):
|
|
"""New feedback evidence is part of every strict/FD/prefix owned-input key."""
|
|
evidence=require_feedback_engine(engine)
|
|
key = (PROTOCOL,evidence.binding,evidence.original.digest,
|
|
tuple((bounds,subset.digest,activation) for bounds,subset,activation in evidence.windows))
|
|
return key if evidence.candidate_policy == LEGACY_POLICY else (*key,evidence.candidate_policy,PROOF_VERSION)
|