1use std::collections::{BTreeMap, BTreeSet};
2
3use serde::{Deserialize, Serialize};
4use sha2::{Digest, Sha256};
5
6use super::is_canonical_sha256;
7use crate::vnext::{
8 CapabilityCatalog, ContractVersion, DeviceId, ExternalModelMetadataId, NodeId, OperationId,
9 PlanHash, ProviderExecutionContractFingerprint, ProviderId, ProviderReplayEquivalence,
10 ResolvedModelPlan, VNextError,
11};
12
13use super::{invalid_plan, ExecutionDeterminismWitnessPlan};
14
15pub const EXECUTION_DETERMINISM_COVERAGE_VERSION: ContractVersion = ContractVersion::new(1, 0);
16pub const EXECUTION_DETERMINISM_EVIDENCE_DENOMINATOR_VERSION: ContractVersion =
17 ContractVersion::new(1, 1);
18
19const MAX_COVERAGE_WIRE_BYTES: usize = 16 * 1024 * 1024;
20const MAX_EVIDENCE_DENOMINATOR_WIRE_BYTES: usize = 128 * 1024 * 1024;
21const MAX_COVERAGE_MODELS: usize = 32;
22const MAX_COVERAGE_PROVIDERS: usize = 512;
23const MAX_COVERAGE_NODES_PER_MODEL: usize = 65_536;
24const MAX_MODEL_KEY_BYTES: usize = 96;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
27#[serde(rename_all = "snake_case")]
28pub enum ExecutionDeterminismComparisonKind {
29 EagerEager,
30 ReplayReplay,
31 EagerReplay,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub enum ExecutionDeterminismProviderCoverage {
37 AllCatalogProviders,
38 SelectedPlanProviders,
39}
40
41impl ExecutionDeterminismComparisonKind {
42 fn for_replay_equivalence(
43 replay_equivalence: ProviderReplayEquivalence,
44 ) -> Vec<ExecutionDeterminismComparisonKind> {
45 let mut comparisons = vec![Self::EagerEager];
46 if replay_equivalence == ProviderReplayEquivalence::BitwiseEagerEquivalent {
47 comparisons.extend([Self::ReplayReplay, Self::EagerReplay]);
48 }
49 comparisons
50 }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
54#[serde(deny_unknown_fields)]
55pub struct ExecutionDeterminismModelPlanIdentity {
56 model_key: String,
57 external_metadata_id: ExternalModelMetadataId,
58 resolved_plan_fingerprint: String,
59 plan_hash: PlanHash,
60 node_ids: Vec<NodeId>,
61}
62
63impl ExecutionDeterminismModelPlanIdentity {
64 pub fn model_key(&self) -> &str {
65 &self.model_key
66 }
67
68 pub fn external_metadata_id(&self) -> &ExternalModelMetadataId {
69 &self.external_metadata_id
70 }
71
72 pub fn resolved_plan_fingerprint(&self) -> &str {
73 &self.resolved_plan_fingerprint
74 }
75
76 pub fn plan_hash(&self) -> &PlanHash {
77 &self.plan_hash
78 }
79
80 pub fn node_ids(&self) -> &[NodeId] {
81 &self.node_ids
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86#[serde(deny_unknown_fields)]
87pub struct ExecutionDeterminismModelProviderSelection {
88 model_key: String,
89 resolved_plan_fingerprint: String,
90 plan_hash: PlanHash,
91 node_ids: Vec<NodeId>,
92}
93
94impl ExecutionDeterminismModelProviderSelection {
95 pub fn model_key(&self) -> &str {
96 &self.model_key
97 }
98
99 pub fn resolved_plan_fingerprint(&self) -> &str {
100 &self.resolved_plan_fingerprint
101 }
102
103 pub fn plan_hash(&self) -> &PlanHash {
104 &self.plan_hash
105 }
106
107 pub fn node_ids(&self) -> &[NodeId] {
108 &self.node_ids
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
113#[serde(deny_unknown_fields)]
114pub struct ExecutionDeterminismCatalogProviderRequirement {
115 operation_id: OperationId,
116 operation_version: ContractVersion,
117 operation_fingerprint: String,
118 provider_id: ProviderId,
119 provider_version: ContractVersion,
120 provider_implementation_fingerprint: String,
121 provider_execution_contract_fingerprint: ProviderExecutionContractFingerprint,
122 replay_equivalence: ProviderReplayEquivalence,
123 required_comparisons: Vec<ExecutionDeterminismComparisonKind>,
124 model_selections: Vec<ExecutionDeterminismModelProviderSelection>,
125}
126
127impl ExecutionDeterminismCatalogProviderRequirement {
128 pub fn operation_id(&self) -> &OperationId {
129 &self.operation_id
130 }
131
132 pub const fn operation_version(&self) -> ContractVersion {
133 self.operation_version
134 }
135
136 pub fn operation_fingerprint(&self) -> &str {
137 &self.operation_fingerprint
138 }
139
140 pub fn provider_id(&self) -> &ProviderId {
141 &self.provider_id
142 }
143
144 pub const fn provider_version(&self) -> ContractVersion {
145 self.provider_version
146 }
147
148 pub fn provider_implementation_fingerprint(&self) -> &str {
149 &self.provider_implementation_fingerprint
150 }
151
152 pub const fn provider_execution_contract_fingerprint(
153 &self,
154 ) -> ProviderExecutionContractFingerprint {
155 self.provider_execution_contract_fingerprint
156 }
157
158 pub const fn replay_equivalence(&self) -> ProviderReplayEquivalence {
159 self.replay_equivalence
160 }
161
162 pub fn required_comparisons(&self) -> &[ExecutionDeterminismComparisonKind] {
163 &self.required_comparisons
164 }
165
166 pub fn model_selections(&self) -> &[ExecutionDeterminismModelProviderSelection] {
167 &self.model_selections
168 }
169
170 fn canonical_key(&self) -> (&OperationId, &ProviderId) {
171 (&self.operation_id, &self.provider_id)
172 }
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
182#[serde(deny_unknown_fields)]
183pub struct ExecutionDeterminismCoverageRegistry {
184 schema_version: ContractVersion,
185 device_id: DeviceId,
186 device_runtime_implementation_fingerprint: String,
187 capability_catalog_fingerprint: String,
188 models: Vec<ExecutionDeterminismModelPlanIdentity>,
189 provider_requirements: Vec<ExecutionDeterminismCatalogProviderRequirement>,
190}
191
192impl ExecutionDeterminismCoverageRegistry {
193 pub fn from_catalog(catalog: &CapabilityCatalog) -> Result<Self, VNextError> {
194 let mut provider_requirements = Vec::new();
195 for (operation_id, providers) in catalog.providers() {
196 let operation = catalog.operations().get(operation_id).ok_or_else(|| {
197 invalid_plan(format!(
198 "determinism coverage catalog provider row `{operation_id}` has no operation"
199 ))
200 })?;
201 let operation_fingerprint = operation.fingerprint()?;
202 for provider in providers {
203 let semantics = provider.execution_semantics();
204 provider_requirements.push(ExecutionDeterminismCatalogProviderRequirement {
205 operation_id: operation_id.clone(),
206 operation_version: operation.version,
207 operation_fingerprint: operation_fingerprint.clone(),
208 provider_id: provider.provider_id().clone(),
209 provider_version: provider.version(),
210 provider_implementation_fingerprint: provider
211 .provider_implementation_fingerprint()
212 .to_owned(),
213 provider_execution_contract_fingerprint: semantics.contract_fingerprint(),
214 replay_equivalence: semantics.replay_equivalence(),
215 required_comparisons:
216 ExecutionDeterminismComparisonKind::for_replay_equivalence(
217 semantics.replay_equivalence(),
218 ),
219 model_selections: Vec::new(),
220 });
221 }
222 }
223 provider_requirements
224 .sort_by(|left, right| left.canonical_key().cmp(&right.canonical_key()));
225 let registry = Self {
226 schema_version: EXECUTION_DETERMINISM_COVERAGE_VERSION,
227 device_id: catalog.device().id.clone(),
228 device_runtime_implementation_fingerprint: catalog
229 .device()
230 .runtime_implementation_fingerprint
231 .clone(),
232 capability_catalog_fingerprint: catalog.fingerprint()?,
233 models: Vec::new(),
234 provider_requirements,
235 };
236 registry.validate_shape(false)?;
237 Ok(registry)
238 }
239
240 pub fn try_add_resolved_model_plan(
241 &mut self,
242 model_key: impl Into<String>,
243 plan: &ResolvedModelPlan,
244 ) -> Result<(), VNextError> {
245 let model_key = model_key.into();
246 validate_model_key(&model_key)?;
247 if self.models.len() >= MAX_COVERAGE_MODELS {
248 return Err(invalid_plan(
249 "execution determinism coverage model count exceeds its bound",
250 ));
251 }
252 if self.models.iter().any(|model| {
253 model.model_key == model_key
254 || model.external_metadata_id == plan.parts().external_metadata_id
255 || model.resolved_plan_fingerprint == plan.fingerprint()
256 }) {
257 return Err(invalid_plan(
258 "execution determinism coverage cannot reuse a model key, metadata identity, or resolved plan",
259 ));
260 }
261 if plan.parts().device.id != self.device_id
262 || plan.parts().device.runtime_implementation_fingerprint
263 != self.device_runtime_implementation_fingerprint
264 || plan.parts().capabilities.fingerprint()? != self.capability_catalog_fingerprint
265 {
266 return Err(invalid_plan(
267 "resolved model plan differs from the determinism coverage catalog or device runtime",
268 ));
269 }
270 let plan_nodes = plan.execution_plan().payload().nodes();
271 if plan_nodes.is_empty() || plan_nodes.len() > MAX_COVERAGE_NODES_PER_MODEL {
272 return Err(invalid_plan(
273 "resolved model plan is empty or exceeds the determinism coverage node bound",
274 ));
275 }
276
277 let mut selected_nodes = BTreeMap::<(OperationId, ProviderId), Vec<NodeId>>::new();
278 for node in plan_nodes {
279 let key = (
280 node.operation_id().clone(),
281 node.selection().selected_provider().clone(),
282 );
283 let requirement = self
284 .provider_requirements
285 .binary_search_by(|candidate| candidate.canonical_key().cmp(&(&key.0, &key.1)))
286 .ok()
287 .and_then(|index| self.provider_requirements.get(index))
288 .ok_or_else(|| {
289 invalid_plan(format!(
290 "resolved node `{}` selected provider `{}` absent from the live determinism catalog",
291 node.id(),
292 node.selection().selected_provider()
293 ))
294 })?;
295 if !requirement
296 .operation_version
297 .satisfies(node.operation_version())
298 {
299 return Err(invalid_plan(format!(
300 "resolved node `{}` requires operation version {}, but the live catalog provides {}",
301 node.id(),
302 node.operation_version(),
303 requirement.operation_version
304 )));
305 }
306 if node.operation_fingerprint() != requirement.operation_fingerprint {
307 return Err(invalid_plan(format!(
308 "resolved node `{}` differs from its live catalog operation fingerprint",
309 node.id()
310 )));
311 }
312 if node.provider_implementation_fingerprint()
313 != requirement.provider_implementation_fingerprint
314 {
315 return Err(invalid_plan(format!(
316 "resolved node `{}` differs from its live catalog provider implementation fingerprint",
317 node.id()
318 )));
319 }
320 if node.provider_execution_semantics().contract_fingerprint()
321 != requirement.provider_execution_contract_fingerprint
322 {
323 return Err(invalid_plan(format!(
324 "resolved node `{}` differs from its live catalog provider execution contract",
325 node.id()
326 )));
327 }
328 if node.provider_execution_semantics().replay_equivalence()
329 != requirement.replay_equivalence
330 {
331 return Err(invalid_plan(format!(
332 "resolved node `{}` differs from its live catalog replay equivalence",
333 node.id()
334 )));
335 }
336 selected_nodes
337 .entry(key)
338 .or_default()
339 .push(node.id().clone());
340 }
341
342 let identity = ExecutionDeterminismModelPlanIdentity {
343 model_key: model_key.clone(),
344 external_metadata_id: plan.parts().external_metadata_id.clone(),
345 resolved_plan_fingerprint: plan.fingerprint().to_owned(),
346 plan_hash: plan.execution_plan().plan_hash().clone(),
347 node_ids: plan_nodes.iter().map(|node| node.id().clone()).collect(),
348 };
349 let mut next_requirements = self.provider_requirements.clone();
350 for requirement in &mut next_requirements {
351 if let Some(node_ids) = selected_nodes.remove(&(
352 requirement.operation_id.clone(),
353 requirement.provider_id.clone(),
354 )) {
355 requirement
356 .model_selections
357 .push(ExecutionDeterminismModelProviderSelection {
358 model_key: model_key.clone(),
359 resolved_plan_fingerprint: identity.resolved_plan_fingerprint.clone(),
360 plan_hash: identity.plan_hash.clone(),
361 node_ids,
362 });
363 requirement
364 .model_selections
365 .sort_by(|left, right| left.model_key.cmp(&right.model_key));
366 }
367 }
368 if !selected_nodes.is_empty() {
369 return Err(invalid_plan(
370 "resolved model plan left unmatched determinism provider selections",
371 ));
372 }
373
374 let mut next_models = self.models.clone();
375 next_models.push(identity);
376 next_models.sort_by(|left, right| left.model_key.cmp(&right.model_key));
377 let candidate = Self {
378 schema_version: self.schema_version,
379 device_id: self.device_id.clone(),
380 device_runtime_implementation_fingerprint: self
381 .device_runtime_implementation_fingerprint
382 .clone(),
383 capability_catalog_fingerprint: self.capability_catalog_fingerprint.clone(),
384 models: next_models,
385 provider_requirements: next_requirements,
386 };
387 candidate.validate_shape(true)?;
388 *self = candidate;
389 Ok(())
390 }
391
392 pub const fn schema_version(&self) -> ContractVersion {
393 self.schema_version
394 }
395
396 pub fn device_id(&self) -> &DeviceId {
397 &self.device_id
398 }
399
400 pub fn device_runtime_implementation_fingerprint(&self) -> &str {
401 &self.device_runtime_implementation_fingerprint
402 }
403
404 pub fn capability_catalog_fingerprint(&self) -> &str {
405 &self.capability_catalog_fingerprint
406 }
407
408 pub fn models(&self) -> &[ExecutionDeterminismModelPlanIdentity] {
409 &self.models
410 }
411
412 pub fn provider_requirements(&self) -> &[ExecutionDeterminismCatalogProviderRequirement] {
413 &self.provider_requirements
414 }
415
416 pub fn unselected_provider_requirements(
417 &self,
418 ) -> impl Iterator<Item = &ExecutionDeterminismCatalogProviderRequirement> {
419 self.provider_requirements
420 .iter()
421 .filter(|requirement| requirement.model_selections.is_empty())
422 }
423
424 pub fn to_json(&self) -> Result<Vec<u8>, VNextError> {
425 self.validate_shape(true)?;
426 serde_json::to_vec_pretty(self).map_err(|error| VNextError::Serialization {
427 context: "serialize execution determinism coverage registry",
428 message: error.to_string(),
429 })
430 }
431
432 pub fn fingerprint(&self) -> Result<String, VNextError> {
433 Ok(format!("{:x}", Sha256::digest(self.to_json()?)))
434 }
435
436 pub fn decode_untrusted(bytes: &[u8]) -> Result<Self, VNextError> {
437 if bytes.len() > MAX_COVERAGE_WIRE_BYTES {
438 return Err(invalid_plan(
439 "execution determinism coverage registry exceeds its wire bound",
440 ));
441 }
442 let registry =
443 serde_json::from_slice::<Self>(bytes).map_err(|error| VNextError::Serialization {
444 context: "decode execution determinism coverage registry",
445 message: error.to_string(),
446 })?;
447 registry.validate_shape(true)?;
448 Ok(registry)
449 }
450
451 fn validate_shape(&self, require_models: bool) -> Result<(), VNextError> {
452 if self.schema_version != EXECUTION_DETERMINISM_COVERAGE_VERSION
453 || !is_canonical_sha256(&self.device_runtime_implementation_fingerprint)
454 || !is_canonical_sha256(&self.capability_catalog_fingerprint)
455 || self.provider_requirements.is_empty()
456 || self.provider_requirements.len() > MAX_COVERAGE_PROVIDERS
457 || self.models.len() > MAX_COVERAGE_MODELS
458 || (require_models && self.models.is_empty())
459 {
460 return Err(invalid_plan(
461 "execution determinism coverage registry identity or cardinality is invalid",
462 ));
463 }
464 if self
465 .models
466 .windows(2)
467 .any(|pair| pair[0].model_key >= pair[1].model_key)
468 || self
469 .provider_requirements
470 .windows(2)
471 .any(|pair| pair[0].canonical_key() >= pair[1].canonical_key())
472 {
473 return Err(invalid_plan(
474 "execution determinism coverage rows are not canonical and unique",
475 ));
476 }
477
478 let mut model_nodes = BTreeMap::<&str, BTreeSet<&NodeId>>::new();
479 let mut model_identities = BTreeMap::new();
480 let mut metadata_ids = BTreeSet::new();
481 let mut resolved_fingerprints = BTreeSet::new();
482 for model in &self.models {
483 validate_model_key(&model.model_key)?;
484 if !is_canonical_sha256(&model.resolved_plan_fingerprint)
485 || model.node_ids.is_empty()
486 || model.node_ids.len() > MAX_COVERAGE_NODES_PER_MODEL
487 || model.node_ids.iter().collect::<BTreeSet<_>>().len() != model.node_ids.len()
488 || !metadata_ids.insert(&model.external_metadata_id)
489 || !resolved_fingerprints.insert(model.resolved_plan_fingerprint.as_str())
490 {
491 return Err(invalid_plan(
492 "execution determinism model identity or node denominator is invalid",
493 ));
494 }
495 model_nodes.insert(model.model_key.as_str(), BTreeSet::new());
496 model_identities.insert(model.model_key.as_str(), model);
497 }
498
499 for requirement in &self.provider_requirements {
500 let expected_comparisons = ExecutionDeterminismComparisonKind::for_replay_equivalence(
501 requirement.replay_equivalence,
502 );
503 if requirement.operation_version.major == 0
504 || requirement.provider_version.major == 0
505 || !is_canonical_sha256(&requirement.operation_fingerprint)
506 || !is_canonical_sha256(&requirement.provider_implementation_fingerprint)
507 || requirement.required_comparisons != expected_comparisons
508 || requirement
509 .model_selections
510 .windows(2)
511 .any(|pair| pair[0].model_key >= pair[1].model_key)
512 {
513 return Err(invalid_plan(
514 "execution determinism provider requirement is invalid",
515 ));
516 }
517 for selection in &requirement.model_selections {
518 let model = model_identities
519 .get(selection.model_key.as_str())
520 .ok_or_else(|| {
521 invalid_plan(
522 "execution determinism provider selection references an unknown model",
523 )
524 })?;
525 if selection.resolved_plan_fingerprint != model.resolved_plan_fingerprint
526 || selection.plan_hash != model.plan_hash
527 || selection.node_ids.is_empty()
528 || selection.node_ids.iter().collect::<BTreeSet<_>>().len()
529 != selection.node_ids.len()
530 {
531 return Err(invalid_plan(
532 "execution determinism provider selection identity is invalid",
533 ));
534 }
535 let covered = model_nodes
536 .get_mut(selection.model_key.as_str())
537 .expect("validated model coverage denominator exists");
538 for node_id in &selection.node_ids {
539 if !covered.insert(node_id) {
540 return Err(invalid_plan(
541 "execution determinism model node is selected by multiple providers",
542 ));
543 }
544 }
545 }
546 }
547 for (model_key, covered) in model_nodes {
548 let expected = model_identities[model_key]
549 .node_ids
550 .iter()
551 .collect::<BTreeSet<_>>();
552 if covered != expected {
553 return Err(invalid_plan(
554 "execution determinism provider selections do not cover the resolved plan exactly",
555 ));
556 }
557 }
558 Ok(())
559 }
560}
561
562#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
569#[serde(deny_unknown_fields)]
570pub struct ExecutionDeterminismProviderEvidenceDenominator {
571 model_key: String,
572 resolved_plan_fingerprint: String,
573 plan_hash: PlanHash,
574 operation_id: OperationId,
575 operation_fingerprint: String,
576 provider_id: ProviderId,
577 provider_implementation_fingerprint: String,
578 provider_execution_contract_fingerprint: ProviderExecutionContractFingerprint,
579 replay_equivalence: ProviderReplayEquivalence,
580 required_comparisons: Vec<ExecutionDeterminismComparisonKind>,
581 node_ids: Vec<NodeId>,
582 witness_plan_fingerprint: String,
583 witness_plan: ExecutionDeterminismWitnessPlan,
584}
585
586impl ExecutionDeterminismProviderEvidenceDenominator {
587 pub fn model_key(&self) -> &str {
588 &self.model_key
589 }
590
591 pub fn operation_id(&self) -> &OperationId {
592 &self.operation_id
593 }
594
595 pub fn provider_id(&self) -> &ProviderId {
596 &self.provider_id
597 }
598
599 pub fn node_ids(&self) -> &[NodeId] {
600 &self.node_ids
601 }
602
603 pub fn required_comparisons(&self) -> &[ExecutionDeterminismComparisonKind] {
604 &self.required_comparisons
605 }
606
607 pub fn witness_plan_fingerprint(&self) -> &str {
608 &self.witness_plan_fingerprint
609 }
610
611 pub fn witness_plan(&self) -> &ExecutionDeterminismWitnessPlan {
612 &self.witness_plan
613 }
614
615 fn canonical_key(&self) -> (&str, &OperationId, &ProviderId) {
616 (&self.model_key, &self.operation_id, &self.provider_id)
617 }
618}
619
620#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
627#[serde(deny_unknown_fields)]
628pub struct ExecutionDeterminismEvidenceDenominator {
629 schema_version: ContractVersion,
630 provider_coverage: ExecutionDeterminismProviderCoverage,
631 coverage: ExecutionDeterminismCoverageRegistry,
632 provider_evidence: Vec<ExecutionDeterminismProviderEvidenceDenominator>,
633}
634
635impl ExecutionDeterminismEvidenceDenominator {
636 pub fn from_catalog_and_resolved_plans(
637 catalog: &CapabilityCatalog,
638 plans: &[(&str, &ResolvedModelPlan)],
639 ) -> Result<Self, VNextError> {
640 Self::from_catalog_and_resolved_plans_with_provider_coverage(
641 catalog,
642 plans,
643 ExecutionDeterminismProviderCoverage::AllCatalogProviders,
644 )
645 }
646
647 pub fn from_catalog_and_resolved_plans_with_provider_coverage(
648 catalog: &CapabilityCatalog,
649 plans: &[(&str, &ResolvedModelPlan)],
650 provider_coverage: ExecutionDeterminismProviderCoverage,
651 ) -> Result<Self, VNextError> {
652 if plans.is_empty() || plans.len() > MAX_COVERAGE_MODELS {
653 return Err(invalid_plan(
654 "execution determinism evidence model denominator is empty or exceeds its bound",
655 ));
656 }
657 let mut plan_by_key = BTreeMap::new();
658 let mut coverage = ExecutionDeterminismCoverageRegistry::from_catalog(catalog)?;
659 for (model_key, plan) in plans {
660 validate_model_key(model_key)?;
661 if plan_by_key.insert((*model_key).to_owned(), *plan).is_some() {
662 return Err(invalid_plan(
663 "execution determinism evidence model keys must be unique",
664 ));
665 }
666 coverage.try_add_resolved_model_plan(*model_key, plan)?;
667 }
668 if provider_coverage == ExecutionDeterminismProviderCoverage::AllCatalogProviders
669 && coverage.unselected_provider_requirements().next().is_some()
670 {
671 return Err(invalid_plan(
672 "execution determinism live catalog contains a provider absent from all resolved plans",
673 ));
674 }
675
676 let mut provider_evidence = Vec::new();
677 for requirement in &coverage.provider_requirements {
678 for selection in &requirement.model_selections {
679 let plan = plan_by_key
680 .get(selection.model_key.as_str())
681 .expect("coverage model came from the exact plan map");
682 let witness_plan = plan
683 .execution_plan()
684 .determinism_witness_plan_for_nodes(&selection.node_ids)?;
685 let witness_plan_fingerprint = witness_plan.fingerprint()?;
686 provider_evidence.push(ExecutionDeterminismProviderEvidenceDenominator {
687 model_key: selection.model_key.clone(),
688 resolved_plan_fingerprint: selection.resolved_plan_fingerprint.clone(),
689 plan_hash: selection.plan_hash.clone(),
690 operation_id: requirement.operation_id.clone(),
691 operation_fingerprint: requirement.operation_fingerprint.clone(),
692 provider_id: requirement.provider_id.clone(),
693 provider_implementation_fingerprint: requirement
694 .provider_implementation_fingerprint
695 .clone(),
696 provider_execution_contract_fingerprint: requirement
697 .provider_execution_contract_fingerprint,
698 replay_equivalence: requirement.replay_equivalence,
699 required_comparisons: requirement.required_comparisons.clone(),
700 node_ids: selection.node_ids.clone(),
701 witness_plan_fingerprint,
702 witness_plan,
703 });
704 }
705 }
706 provider_evidence.sort_by(|left, right| left.canonical_key().cmp(&right.canonical_key()));
707 let denominator = Self {
708 schema_version: EXECUTION_DETERMINISM_EVIDENCE_DENOMINATOR_VERSION,
709 provider_coverage,
710 coverage,
711 provider_evidence,
712 };
713 denominator.validate_shape()?;
714 Ok(denominator)
715 }
716
717 pub const fn schema_version(&self) -> ContractVersion {
718 self.schema_version
719 }
720
721 pub const fn provider_coverage(&self) -> ExecutionDeterminismProviderCoverage {
722 self.provider_coverage
723 }
724
725 pub fn coverage(&self) -> &ExecutionDeterminismCoverageRegistry {
726 &self.coverage
727 }
728
729 pub fn provider_evidence(&self) -> &[ExecutionDeterminismProviderEvidenceDenominator] {
730 &self.provider_evidence
731 }
732
733 pub fn to_json(&self) -> Result<Vec<u8>, VNextError> {
734 self.validate_shape()?;
735 serde_json::to_vec_pretty(self).map_err(|error| VNextError::Serialization {
736 context: "serialize execution determinism evidence denominator",
737 message: error.to_string(),
738 })
739 }
740
741 pub fn fingerprint(&self) -> Result<String, VNextError> {
742 Ok(format!("{:x}", Sha256::digest(self.to_json()?)))
743 }
744
745 pub fn decode_untrusted(bytes: &[u8]) -> Result<Self, VNextError> {
746 if bytes.len() > MAX_EVIDENCE_DENOMINATOR_WIRE_BYTES {
747 return Err(invalid_plan(
748 "execution determinism evidence denominator exceeds its wire bound",
749 ));
750 }
751 let denominator =
752 serde_json::from_slice::<Self>(bytes).map_err(|error| VNextError::Serialization {
753 context: "decode execution determinism evidence denominator",
754 message: error.to_string(),
755 })?;
756 denominator.validate_shape()?;
757 Ok(denominator)
758 }
759
760 fn validate_shape(&self) -> Result<(), VNextError> {
761 self.coverage.validate_shape(true)?;
762 if self.schema_version != EXECUTION_DETERMINISM_EVIDENCE_DENOMINATOR_VERSION
763 || self.provider_evidence.is_empty()
764 || self.provider_evidence.len()
765 > MAX_COVERAGE_MODELS.saturating_mul(MAX_COVERAGE_PROVIDERS)
766 || (self.provider_coverage == ExecutionDeterminismProviderCoverage::AllCatalogProviders
767 && self
768 .coverage
769 .unselected_provider_requirements()
770 .next()
771 .is_some())
772 || self
773 .provider_evidence
774 .windows(2)
775 .any(|pair| pair[0].canonical_key() >= pair[1].canonical_key())
776 {
777 return Err(invalid_plan(
778 "execution determinism evidence denominator identity or cardinality is invalid",
779 ));
780 }
781
782 let requirements = self
783 .coverage
784 .provider_requirements
785 .iter()
786 .map(|requirement| (requirement.canonical_key(), requirement))
787 .collect::<BTreeMap<_, _>>();
788 let models = self
789 .coverage
790 .models
791 .iter()
792 .map(|model| (model.model_key.as_str(), model))
793 .collect::<BTreeMap<_, _>>();
794 let mut expected = BTreeSet::new();
795 for requirement in &self.coverage.provider_requirements {
796 for selection in &requirement.model_selections {
797 expected.insert((
798 selection.model_key.as_str(),
799 &requirement.operation_id,
800 &requirement.provider_id,
801 ));
802 }
803 }
804 let actual = self
805 .provider_evidence
806 .iter()
807 .map(ExecutionDeterminismProviderEvidenceDenominator::canonical_key)
808 .collect::<BTreeSet<_>>();
809 if actual != expected {
810 return Err(invalid_plan(
811 "execution determinism provider evidence does not equal the live plan denominator",
812 ));
813 }
814
815 for evidence in &self.provider_evidence {
816 let requirement = requirements
817 .get(&(&evidence.operation_id, &evidence.provider_id))
818 .expect("validated evidence key exists in coverage");
819 let selection = requirement
820 .model_selections
821 .iter()
822 .find(|selection| selection.model_key == evidence.model_key)
823 .expect("validated evidence key has a model selection");
824 let model = models
825 .get(evidence.model_key.as_str())
826 .expect("validated evidence model exists in coverage");
827 evidence.witness_plan.validate_shape()?;
828 if evidence.resolved_plan_fingerprint != selection.resolved_plan_fingerprint
829 || evidence.resolved_plan_fingerprint != model.resolved_plan_fingerprint
830 || evidence.plan_hash != selection.plan_hash
831 || evidence.plan_hash != model.plan_hash
832 || evidence.operation_fingerprint != requirement.operation_fingerprint
833 || evidence.provider_implementation_fingerprint
834 != requirement.provider_implementation_fingerprint
835 || evidence.provider_execution_contract_fingerprint
836 != requirement.provider_execution_contract_fingerprint
837 || evidence.replay_equivalence != requirement.replay_equivalence
838 || evidence.required_comparisons != requirement.required_comparisons
839 || evidence.node_ids != selection.node_ids
840 || evidence.witness_plan.plan_hash() != &evidence.plan_hash
841 || evidence.witness_plan.node_ids() != evidence.node_ids
842 || evidence.witness_plan.fingerprint()? != evidence.witness_plan_fingerprint
843 || evidence.witness_plan.witnesses().iter().any(|witness| {
844 witness.provider_id() != &evidence.provider_id
845 || witness.provider_implementation_fingerprint()
846 != evidence.provider_implementation_fingerprint
847 || witness.provider_execution_contract_fingerprint()
848 != evidence.provider_execution_contract_fingerprint
849 })
850 {
851 return Err(invalid_plan(
852 "execution determinism provider evidence differs from its live catalog, plan, or witness denominator",
853 ));
854 }
855 }
856 Ok(())
857 }
858}
859
860fn validate_model_key(model_key: &str) -> Result<(), VNextError> {
861 if model_key.is_empty()
862 || model_key.len() > MAX_MODEL_KEY_BYTES
863 || !model_key
864 .bytes()
865 .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'_' | b'-' | b'/'))
866 {
867 return Err(invalid_plan(
868 "execution determinism model key is empty or non-canonical",
869 ));
870 }
871 Ok(())
872}