use std::fmt; use borsh::{BorshDeserialize, BorshSerialize}; use derive_more::Constructor; use mpc_primitives::hash::{LauncherDockerComposeHash, NodeImageHash, Sha384Digest}; use near_mpc_crypto_types::Ed25519PublicKey; use serde::{Deserialize, Serialize}; use serde_with::{hex::Hex, serde_as}; /// A variable-length byte vector serialized as a hex string in JSON. #[serde_as] #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, derive_more::From, derive_more::Into, derive_more::Deref, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] #[serde(transparent)] pub struct HexVec(#[serde_as(as = "Hex")] pub Vec); #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub enum Attestation { Dstack(DstackAttestation), Mock(MockAttestation), } #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub enum VerifiedAttestation { Dstack(VerifiedDstackAttestation), Mock(MockAttestation), } #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct VerifiedDstackAttestation { /// The digest of the MPC image running. pub mpc_image_hash: NodeImageHash, /// The digest of the launcher compose file running. pub launcher_compose_hash: LauncherDockerComposeHash, /// Unix time stamp for when this attestation expires. pub expiry_timestamp_seconds: u64, /// The OS measurements that were verified during initial attestation. pub measurements: VerifiedMeasurements, } #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct VerifiedMeasurements { pub mrtd: Sha384Digest, pub rtmr0: Sha384Digest, pub rtmr1: Sha384Digest, pub rtmr2: Sha384Digest, pub key_provider_event_digest: Sha384Digest, } #[derive( Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Constructor, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct DstackAttestation { pub quote: HexVec, pub collateral: Collateral, pub tcb_info: TcbInfo, } #[expect(clippy::large_enum_variant)] #[derive( Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub enum MockAttestation { /// Always pass validation Valid, /// Always fails validation Invalid, /// Pass validation depending on the set constraints WithConstraints { mpc_docker_image_hash: Option, launcher_docker_compose_hash: Option, /// Unix time stamp for when this attestation expires. expiry_timestamp_seconds: Option, expected_measurements: Option, }, } // TODO(#3494): superseded by `tee_verifier_interface::Collateral`; remove // this serde-carrying copy once `mpc-contract` consumes the Borsh mirrors. #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct Collateral { pub pck_crl_issuer_chain: String, pub root_ca_crl: HexVec, pub pck_crl: HexVec, pub tcb_info_issuer_chain: String, pub tcb_info: String, pub tcb_info_signature: HexVec, pub qe_identity_issuer_chain: String, pub qe_identity: String, pub qe_identity_signature: HexVec, pub pck_certificate_chain: Option, } impl fmt::Debug for DstackAttestation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { const MAX_BYTES: usize = 2048; fn truncate_debug(value: &T, max_bytes: usize) -> String { let debug_str = format!("{:?}", value); if debug_str.len() <= max_bytes { debug_str } else { format!( "{}... (truncated {} bytes)", &debug_str[..max_bytes], debug_str.len() - max_bytes ) } } f.debug_struct("DstackAttestation") .field("quote", &truncate_debug(&self.quote, MAX_BYTES)) .field("collateral", &truncate_debug(&self.collateral, MAX_BYTES)) .field("tcb_info", &truncate_debug(&self.tcb_info, MAX_BYTES)) .finish() } } #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] // This is a hand-maintained mirror of the verified `attestation::AppCompose` — the // security-relevant subset, NOT the type used during attestation verification. Keep its security // fields in sync with the verified struct, or it can drift. // TODO(#3425): dedupe with `attestation::AppCompose` (single source of truth) — pending team decision. #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct AppCompose { pub manifest_version: u32, pub name: String, pub runner: String, pub docker_compose_file: String, pub kms_enabled: bool, pub tproxy_enabled: Option, pub gateway_enabled: Option, pub public_logs: bool, pub public_sysinfo: bool, pub local_key_provider_enabled: bool, pub key_provider_id: Option, pub allowed_envs: Vec, pub no_instance_id: bool, pub secure_time: Option, pub pre_launch_script: Option, pub init_script: Option, pub bash_script: Option, } /// Trusted Computing Base information structure #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct TcbInfo { /// The measurement root of trust pub mrtd: String, /// The value of RTMR0 (Runtime Measurement Register 0) pub rtmr0: String, /// The value of RTMR1 (Runtime Measurement Register 1) pub rtmr1: String, /// The value of RTMR2 (Runtime Measurement Register 2) pub rtmr2: String, /// The value of RTMR3 (Runtime Measurement Register 3) pub rtmr3: String, /// The hash of the OS image. This is empty if the OS image is not measured by KMS. #[serde(default)] pub os_image_hash: String, /// The hash of the compose configuration pub compose_hash: String, /// The device identifier pub device_id: String, /// The app compose pub app_compose: String, /// The event log entries pub event_log: Vec, } /// Represents an event log entry in the system #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] #[cfg_attr( all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema) )] pub struct EventLog { /// The index of the IMR (Integrity Measurement Register) pub imr: u32, /// The type of event being logged pub event_type: u32, /// The cryptographic digest of the event pub digest: String, /// The type of event as a string pub event: String, /// The payload data associated with the event pub event_payload: String, } /// Arguments for the `submit_participant_info` contract call. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SubmitParticipantInfoArgs { pub proposed_participant_attestation: Attestation, pub tls_public_key: Ed25519PublicKey, }