refactor(attestation): extract attestation-types crate without dcap-qvl#3245
Draft
pbeza wants to merge 3 commits into
Draft
refactor(attestation): extract attestation-types crate without dcap-qvl#3245pbeza wants to merge 3 commits into
pbeza wants to merge 3 commits into
Conversation
…undary Introduces a no_std crate carrying the Borsh-stable types that cross the `tee-verifier` contract boundary. The crate has no `dcap-qvl` dependency so it can be linked into consumer contracts (e.g. `mpc-contract`) without dragging `ring`/`webpki`/X.509 parsing into their WASM. Types: - `QuoteBytes`, `Collateral`: standalone mirrors of `dcap_qvl`'s quote bytes and `QuoteCollateralV3`. - `VerifiedReport`, `Report`, `TDReport10`, `TDReport15`, `EnclaveReport`, `TcbStatus`, `TcbStatusWithAdvisory`: Borsh mirrors of the corresponding `dcap_qvl` types, fields one-to-one for forward-compat. - `VerifierError`: error type for future use. Conversions between these mirrors and the `dcap_qvl` types live in the verifier crate, not here, to avoid the orphan rule and to keep this crate `dcap-qvl`-free. Borsh-schema derives are gated behind an optional `borsh-schema` feature, enabled by the verifier crate when `cargo near build` generates ABI. Part of the work described in docs/design/attestation-verifier-contract.md (PR #3160).
Adds the `tee-verifier` contract — a stateless NEAR contract exposing
one method:
verify_quote(quote: QuoteBytes, collateral: Collateral) -> VerifiedReport
The method reads the current block timestamp inside the contract and
calls `dcap_qvl::verify::verify(quote, collateral, now)`. On success,
the parsed report is converted to the Borsh mirror types from
`tee-verifier-interface` and returned via Borsh. On verification
failure, the method panics with the upstream error rendered as a
string; callers handle this as `PromiseResult::Failed` in their
callback.
The contract has no state and no admin. All policy (allowlists,
report-data binding, RTMR3 replay, app-compose validation, etc.) is
the caller's responsibility — only the cryptographic dcap-qvl part
lives here.
Includes:
- `tee_verifier::TeeVerifier` (empty state struct, one method).
- `tee_verifier::conversions` (free functions converting between
`dcap_qvl` types and the mirror types in `tee-verifier-interface`;
free functions rather than `From` impls because of the orphan rule).
- An integration test (`tests/verify_quote.rs`) that calls
`verify_quote` directly against the real Dstack quote+collateral
fixture from `test-utils`, asserting the returned `VerifiedReport`
has status `UpToDate`, no advisory IDs, and a TD10 report.
WASM size (non-reproducible, default release): ~518 KiB.
This is the v1 verifier from
`docs/design/attestation-verifier-contract.md` (#3160). A follow-up
PR will wire `mpc-contract`'s `submit_participant_info` into it via
Promise + callback.
Stacked on #3235.
…-qvl Pure crate split, no behaviour change. Sets up the WASM-size win that the follow-up PR (mpc-contract Promise refactor) will land. What moves: - `app_compose`, `measurements`, `report_data`, `tcb_info` modules and their assets — none of these touched `dcap-qvl` to begin with. - The post-DCAP verification helpers (`verify_tcb_status`, `verify_report_data`, `verify_rtmr3`, `verify_app_compose`, `verify_any_measurements`, `verify_static_rtmrs`, `verify_key_provider_digest`, `verify_event_log_rtmr3`, `validate_app_compose_config`, `compare_hashes`, `compare_hex_hashes`, plus the `OrErr` and `GetSingleEvent` traits and `VerificationError`) — refactored from private methods on `DstackAttestation` to free functions in `attestation_types::verify_post_dcap`, taking the `tee_verifier_interface::VerifiedReport` mirror instead of the `dcap_qvl` type. What stays in `attestation`: - `DstackAttestation::verify` (the one and only `dcap_qvl::verify::verify` call site). It now converts the dcap-qvl-returned report to the Borsh mirror once and calls the free functions on it. - The `Collateral` newtype and `QuoteBytes` newtype. Their dedup with the `tee-verifier-interface` mirrors is deferred to a later PR. What this enables (next PR): - `mpc-contract` can depend on `attestation-types` alone (no `dcap-qvl`) and call the post-DCAP helpers from a Promise callback that receives the verifier-returned `VerifiedReport`. That is the actual WASM-size win for NEP-509. Drops the dead `TryFrom<dcap_qvl::verify::VerifiedReport> for Measurements` impl (no callers anywhere in the codebase). Re-exports the moved modules from `attestation::lib.rs` so existing consumers (`mpc-attestation`, `tee-authority`, `attestation-cli`, etc.) keep their import paths unchanged. Part of the verifier breakout from docs/design/attestation-verifier-contract.md (#3160). Stacked on #3237.
4cf10c7 to
6d62b22
Compare
This was referenced May 15, 2026
6d043fe to
cf72a5a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3267
Pure crate split, no behaviour change. Stacked on #3237. Sets up the WASM-size win that the follow-up PR (
mpc-contractPromise refactor) will land.What moves into the new
attestation-typescrateapp_compose,measurements,report_data,tcb_infomodules — none of these toucheddcap-qvlto begin with.DstackAttestationinto free functions inattestation_types::verify_post_dcap, taking thetee_verifier_interface::VerifiedReportmirror instead of thedcap_qvltype. Same logic, byte-for-byte.What stays in
attestationDstackAttestation::verify— the one and onlydcap_qvl::verify::verifycall site. It now converts the upstream report to the Borsh mirror once and calls the free functions on it.Collateralnewtype andQuoteBytesnewtype. Their dedup with thetee-verifier-interfacemirrors is deferred to a later PR (tee-authorityand friends need a migration path).What this enables (next PR, stacked on this one)
mpc-contractcan depend onattestation-typesalone — nodcap-qvl— and call the post-DCAP helpers from a Promise callback that receives the verifier-returnedVerifiedReport. That is the actual WASM-size win for NEP-509.Drive-bys
TryFrom<dcap_qvl::verify::VerifiedReport> for Measurementsimpl (no callers anywhere in the codebase).attestation::lib.rsso existing consumers (mpc-attestation,tee-authority,attestation-cli, etc.) keep their import paths unchanged.Part of the verifier breakout described in
docs/design/attestation-verifier-contract.md(#3160).