Skip to content

feat(tee-verifier-interface): Borsh DTOs for the verifier contract boundary#3235

Draft
pbeza wants to merge 1 commit into
mainfrom
feat/tee-verifier-interface
Draft

feat(tee-verifier-interface): Borsh DTOs for the verifier contract boundary#3235
pbeza wants to merge 1 commit into
mainfrom
feat/tee-verifier-interface

Conversation

@pbeza
Copy link
Copy Markdown
Contributor

@pbeza pbeza commented May 14, 2026

Closes #3265

Adds crates/tee-verifier-interface: a no_std crate of Borsh DTOs that cross the tee-verifier contract boundary. First of two stacked PRs implementing v1 from docs/design/attestation-verifier-contract.md (#3160).

Types

  • QuoteBytes, Collateral: standalone mirrors of dcap_qvl's quote bytes and QuoteCollateralV3.
  • VerifiedReport, Report, TDReport10, TDReport15, EnclaveReport, TcbStatus, TcbStatusWithAdvisory: field-for-field Borsh mirrors of the corresponding dcap_qvl types.
  • VerifierError: reserved for future use.

dcap-qvl is not a dependency. The mirror is the boundary that keeps dcap-qvl (and ring/webpki/X.509) out of any consumer's WASM. The From<dcap_qvl::...> conversions live in the verifier crate (next PR), not here, to avoid orphan-rule violations.

borsh-schema feature gates BorshSchema derives required by cargo near build ABI generation.

Why a separate crate instead of folding into attestation?

The point of a separate crate is that it's the only DTO crate mpc-contract (and future consumers like Proximity and Defuse) can depend on to talk to the verifier without re-linking the dcap-qvl / ring / webpki / x509-cert closure into their own WASM — which is the WASM-size goal that motivated this work. Folding the types into the existing attestation crate would defeat it, since attestation itself transitively depends on dcap-qvl today.

Follow-ups

@pbeza pbeza force-pushed the feat/tee-verifier-interface branch from 5e6fac2 to b3acde8 Compare May 14, 2026 14:35
@pbeza pbeza force-pushed the feat/tee-verifier-interface branch from b3acde8 to 820497e Compare May 15, 2026 09:18
pbeza added a commit that referenced this pull request May 15, 2026
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.
…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).
@pbeza pbeza force-pushed the feat/tee-verifier-interface branch from 820497e to 2e70aa9 Compare May 15, 2026 10:20
pbeza added a commit that referenced this pull request May 15, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce tee-verifier-interface crate (Borsh wire DTOs)

1 participant