When a plane crashes, we have the black box. When an autonomous vehicle makes a fatal decision, what do we have?
- DVP - Driving Vehicle Protocol Specification: DVP - Driving Vehicle Protocol
The answer, in most cases, is proprietary data locked in a vendor's silo — if it exists at all.
As we deploy AI systems that make life-or-death decisions on public roads, the gap between aviation's century of accountability standards and the automotive industry's "trust us" approach becomes increasingly untenable.
This article introduces the Driving Vehicle Protocol (DVP) — an open standard for creating tamper-evident audit trails of AI decision-making in autonomous vehicles. Think of it as bringing the discipline of aviation's flight recorders to the age of self-driving cars.
The Problem: AI Decisions Without Receipts
Current State of AV Data Logging
Today's autonomous vehicles generate terabytes of data per hour. LiDAR point clouds. Camera feeds. Radar returns. But here's the critical gap:
There's no standardized, tamper-evident record of what the AI decided and why.
Each manufacturer implements their own logging format (if any). When incidents occur, investigations depend on:
- Vendor cooperation
- Proprietary data formats
- Trust that logs haven't been modified
This is fundamentally different from aviation, where flight data recorders follow strict international standards (ED-112A, TSO-C124).
Why This Matters in 2025
Regulatory pressure is mounting:
- UNECE WP.29 is actively developing UN GTR (Global Technical Regulations) for Automated Driving Systems, with work continuing through 2026
- EU AI Act classifies autonomous vehicles as "high-risk AI systems" under Annex III, requiring comprehensive logging (Article 12)
- ISO 21448 (SOTIF) establishes safety frameworks but lacks standardized audit trail specifications
The liability landscape is shifting:
When a Level 3+ ADS is engaged, the manufacturer — not the driver — bears responsibility. Proving what the system did (or didn't do) becomes legally critical.
Enter DVP: The Driving Vehicle Protocol
DVP is an industry application profile within the broader VAP (Verifiable AI Provenance) Framework — the same framework that produced VCP for algorithmic trading.
Core Design Philosophy
The fundamental insight: You don't need to standardize everything — just the audit interface.
┌─────────────────────────────────────────┐
│ Proprietary (Competition Zone) │
│ ───────────────────────────────────── │
│ • Sensor fusion algorithms │
│ • Neural network architectures │
│ • Path planning implementations │
│ • Internal data formats │
└─────────────────────────────────────────┘
↓
Minimal Audit Interface
↓
┌─────────────────────────────────────────┐
│ DVP Common Header (Audit Zone) │
│ ───────────────────────────────────── │
│ ① timestamp - When │
│ ② event_type - What category │
│ ③ action - What happened │
│ ④ model_id - Which AI model │
│ ⑤ prev_hash - Cryptographic chain │
└─────────────────────────────────────────┘
This separation is critical. It means:
- No exposure of competitive IP
- Minimal integration overhead
- Universal auditability
Technical Architecture
Event Types Registry
DVP defines a standardized taxonomy for autonomous driving events:
from enum import Enum
class DVPEventType(Enum):
# Perception Events
PERCEPTION_OBJECT_DETECTED = "PRC_OBJ"
PERCEPTION_LANE_DETECTED = "PRC_LAN"
PERCEPTION_SIGN_DETECTED = "PRC_SGN"
PERCEPTION_CONFIDENCE_LOW = "PRC_LOW"
# Planning Events
PLANNING_PATH_GENERATED = "PLN_PTH"
PLANNING_MANEUVER_DECIDED = "PLN_MNV"
PLANNING_ROUTE_CHANGED = "PLN_RTE"
# Control Commands
CONTROL_ACCELERATION = "CTL_ACC"
CONTROL_BRAKE = "CTL_BRK"
CONTROL_STEERING = "CTL_STR"
CONTROL_EMERGENCY = "CTL_EMG"
# System Events
SYSTEM_MODE_CHANGE = "SYS_MOD"
SYSTEM_TAKEOVER_REQUEST = "SYS_TOR"
SYSTEM_FALLBACK_INITIATED = "SYS_FLB"
SYSTEM_ODD_BOUNDARY = "SYS_ODD" # Operational Design Domain
The Hash Chain: Tamper-Evidence
Like its sibling protocol VCP (for finance), DVP uses hash chains to ensure tamper-evidence:
import hashlib
import json
from nacl.signing import SigningKey
from datetime import datetime, timezone
import uuid
class DVPEventLogger:
"""
DVP-compliant event logger for autonomous driving systems.
Maintains cryptographic hash chain for tamper-evidence.
"""
GENESIS_HASH = "0" * 64
def __init__(self, signing_key: SigningKey, vehicle_id: str, model_id: str):
self.signing_key = signing_key
self.vehicle_id = vehicle_id
self.model_id = model_id
self.prev_hash = self.GENESIS_HASH
def _canonical_json(self, obj: dict) -> bytes:
"""RFC 8785 compliant JSON canonicalization"""
return json.dumps(
obj,
sort_keys=True,
separators=(',', ':'),
ensure_ascii=False
).encode('utf-8')
def log_event(
self,
event_type: str,
action: str,
sensor_inputs: dict = None,
decision_factors: dict = None,
confidence: float = None
) -> dict:
"""
Create a DVP-compliant event record with hash chain linkage.
Returns:
Complete DVP event record with cryptographic signature
"""
# UUIDv7 ensures temporal ordering
event_id = str(uuid.uuid7())
timestamp = datetime.now(timezone.utc).isoformat()
# Construct header (minimal required fields)
header = {
"EventID": event_id,
"Timestamp": timestamp,
"VehicleID": self.vehicle_id,
"EventType": event_type
}
# Construct payload (domain-specific content)
payload = {
"Action": action,
"ModelID": self.model_id
}
if sensor_inputs:
payload["SensorInputs"] = sensor_inputs
if decision_factors:
payload["DecisionFactors"] = decision_factors
if confidence is not None:
payload["Confidence"] = confidence
# Calculate event hash (includes previous hash for chain)
hash_input = (
self._canonical_json(header) +
self._canonical_json(payload) +
self.prev_hash.encode()
)
event_hash = hashlib.sha256(hash_input).hexdigest()
# Create security envelope
security = {
"Version": "1.0",
"PrevHash": self.prev_hash,
"EventHash": event_hash,
"HashAlgo": "SHA256",
"SignAlgo": "ED25519"
}
# Sign the event hash
signature = self.signing_key.sign(event_hash.encode())
security["Signature"] = signature.signature.hex()
# Update chain state
self.prev_hash = event_hash
return {
"Header": header,
"Payload": payload,
"Security": security
}
Real-World Usage Example
from nacl.signing import SigningKey
# Initialize logger for vehicle
signing_key = SigningKey.generate()
logger = DVPEventLogger(
signing_key=signing_key,
vehicle_id="VEH-2025-DEMO-001",
model_id="perception_v3.2.1"
)
# Log perception event: pedestrian detected
event1 = logger.log_event(
event_type="PRC_OBJ",
action="PEDESTRIAN_DETECTED",
sensor_inputs={
"lidar_confidence": 0.94,
"camera_confidence": 0.91,
"radar_detected": True,
"distance_m": 32.5,
"velocity_ms": -1.2 # Approaching
},
decision_factors={
"fusion_method": "late_fusion_v2",
"classification": "pedestrian_adult"
},
confidence=0.93
)
# Log planning decision: emergency brake initiated
event2 = logger.log_event(
event_type="CTL_EMG",
action="EMERGENCY_BRAKE_INITIATED",
sensor_inputs={
"ttc_seconds": 2.1, # Time to collision
"current_speed_ms": 15.6
},
decision_factors={
"trigger": "pedestrian_in_path",
"brake_force_percent": 100,
"predicted_stop_distance_m": 18.2
},
confidence=0.99
)
print(json.dumps(event2, indent=2))
Output:
{
"Header": {
"EventID": "019416a8-7c3f-7000-8000-000000000001",
"Timestamp": "2025-01-03T12:34:56.789012+00:00",
"VehicleID": "VEH-2025-DEMO-001",
"EventType": "CTL_EMG"
},
"Payload": {
"Action": "EMERGENCY_BRAKE_INITIATED",
"ModelID": "perception_v3.2.1",
"SensorInputs": {
"ttc_seconds": 2.1,
"current_speed_ms": 15.6
},
"DecisionFactors": {
"trigger": "pedestrian_in_path",
"brake_force_percent": 100,
"predicted_stop_distance_m": 18.2
},
"Confidence": 0.99
},
"Security": {
"Version": "1.0",
"PrevHash": "a3f2...previous event hash...",
"EventHash": "7b4c...current event hash...",
"HashAlgo": "SHA256",
"SignAlgo": "ED25519",
"Signature": "9d3e...64 byte signature..."
}
}
Merkle Tree Anchoring for External Verification
The Problem with Continuous Logging
An AV generates thousands of events per minute. Anchoring every event to a blockchain would be:
- Prohibitively expensive
- Bandwidth-intensive
- Unnecessary
The Solution: Batch Anchoring
[During Operation - Local Processing]
Event₁ → Event₂ → Event₃ → ... → Eventₙ
↓ ↓ ↓ ↓
[Hash Chain continuously validated locally]
↓ ↓ ↓ ↓
Accumulated in local storage
[Periodic Anchoring - e.g., every 10 minutes or trip end]
┌─────────┐
│ Root │ ← Only this 32-byte hash
└────┬────┘ gets anchored externally
┌─────┴─────┐
┌─┴─┐ ┌─┴─┐
│H₁₂│ │H₃₄│
└─┬─┘ └─┬─┘
┌──┴──┐ ┌──┴──┐
H(E₁) H(E₂) H(E₃) H(E₄)
import hashlib
from typing import List
def build_merkle_tree(event_hashes: List[str]) -> str:
"""
Build RFC 6962-compliant Merkle tree.
Args:
event_hashes: List of event hash strings
Returns:
Merkle root hash
"""
if not event_hashes:
raise ValueError("Cannot build tree from empty list")
# Convert to leaf nodes (0x00 prefix per RFC 6962)
leaves = [
hashlib.sha256(b'\x00' + h.encode()).digest()
for h in event_hashes
]
# Pad to power of 2 if necessary
while len(leaves) & (len(leaves) - 1):
leaves.append(leaves[-1])
# Build tree bottom-up
while len(leaves) > 1:
next_level = []
for i in range(0, len(leaves), 2):
# Internal nodes: 0x01 prefix per RFC 6962
combined = b'\x01' + leaves[i] + leaves[i+1]
next_level.append(hashlib.sha256(combined).digest())
leaves = next_level
return leaves[0].hex()
# Example: Anchor a batch of events
batch_hashes = [event1["Security"]["EventHash"],
event2["Security"]["EventHash"]]
merkle_root = build_merkle_tree(batch_hashes)
print(f"Merkle Root: {merkle_root}")
# This 32-byte hash can be anchored to blockchain/TSA
Regulatory Alignment
EU AI Act Compliance (Article 12)
| Requirement | DVP Implementation |
|---|---|
| Automatic logging | Hash chain captures all decisions |
| Event timestamping | UUIDv7 + ISO 8601 timestamps |
| Operation duration | SYSTEM_MODE_CHANGE events |
| Input data logging | SensorInputs field |
| Reference database | ModelID + version tracking |
UNECE WP.29 Alignment
DVP aligns with the emerging UN GTR on ADS by providing:
- Scenario reconstruction: Complete causal chain from perception to action
- Failure mode documentation: SYSTEM_FALLBACK events with reasons
- Human oversight evidence: TAKEOVER_REQUEST and response timing
- ODD boundary compliance: Operational Design Domain events
ISO 21448 (SOTIF) Support
DVP enables SOTIF compliance by logging:
- Perception confidence levels
- Sensor disagreement events
- Edge case encounters
- System uncertainty acknowledgment
Why This Matters for Developers
If You're Building ADAS/ADS Software
DVP provides a vendor-neutral audit layer that:
- Protects IP: Your algorithms remain proprietary
- Enables compliance: Ready for EU AI Act enforcement
- Supports forensics: Incident reconstruction becomes possible
- Future-proofs: As regulations tighten, you're already compliant
Integration is Minimal
DVP is designed as a sidecar — it doesn't require rewriting your perception stack:
# Minimal integration pattern
class YourExistingPerceptionSystem:
def __init__(self, dvp_logger: DVPEventLogger):
self.dvp = dvp_logger
def process_frame(self, sensor_data):
# Your existing logic unchanged
result = self._run_inference(sensor_data)
# Add DVP logging (one line)
self.dvp.log_event("PRC_OBJ", result.action,
sensor_inputs=result.inputs,
confidence=result.confidence)
return result
The Bigger Picture: VAP Framework
DVP is part of the Verifiable AI Provenance (VAP) Framework — a family of domain-specific protocols sharing common cryptographic foundations:
| Profile | Domain | Status |
|---|---|---|
| VCP | Algorithmic Trading | v1.0 Released |
| DVP | Autonomous Driving | Specification Phase |
| MAP | Medical AI | Planned |
| AAP | Aviation AI | Planned |
| EIP | Energy Infrastructure | Planned |
The shared foundation means:
- Cross-domain expertise transfer
- Unified tooling ecosystem
- Regulatory familiarity
Getting Started
Resources
- VAP Framework Specification: github.com/veritaschain
- Technical Contact: technical@veritaschain.org
- IETF Draft (VCP): datatracker.ietf.org/doc/draft-kamimura-scitt-vcp/
Contributing
DVP is developed by the VeritasChain Standards Organization (VSO) as an open standard. We welcome:
- Automotive OEM feedback
- Tier-1 supplier input
- Regulatory perspective
- Academic collaboration
Contact: standards@veritaschain.org
Conclusion
The autonomous vehicle industry is at an inflection point. The same forces that drove aviation to standardize flight data recorders — accidents, liability, regulation — are now converging on AV.
The question isn't whether standardized AI audit trails will become mandatory. It's who will define them.
DVP offers an open, technically sound, vendor-neutral answer. The code is simple. The cryptography is proven. The regulatory alignment is clear.
The only question is: Will the industry adopt transparency voluntarily, or wait until the first major incident forces it?
This article introduces concepts from the Verifiable AI Provenance (VAP) Framework developed by the VeritasChain Standards Organization. VCP (the finance profile) has been submitted to IETF SCITT working group. DVP specifications are in active development.
About the Author: This article was written as part of the VeritasChain Standards Organization's developer outreach program. For more information, visit veritaschain.org.
Tags: #autonomousdriving #selfdrivingcars #ai #machinelearning #cryptography #opensource #adas #unece #euaiact #audit #compliance #embedded #automotive
Top comments (0)