Skip to content

feat(contract): async TEE attestation verification via verifier contract, drop dcap-qvl - #3664

Closed
pbeza wants to merge 31 commits into
mainfrom
3642-wire-async-tee-attestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract
Closed

feat(contract): async TEE attestation verification via verifier contract, drop dcap-qvl#3664
pbeza wants to merge 31 commits into
mainfrom
3642-wire-async-tee-attestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract

Conversation

@pbeza

@pbeza pbeza commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Closes #3642.

Today the MPC contract verifies a node's Intel TDX attestation synchronously, inside its own WASM, by linking the dcap-qvl library. This PR moves that crypto verification out into a separate tee-verifier contract and makes submit_participant_info asynchronous. The MPC contract stops linking dcap-qvl entirely.

Final slice of #3540, after #3590 (split DCAP from post-DCAP) and #3626 (verifier-account voting).

WASM size impact

Dropping dcap-qvl shrinks the contract WASM by ~296 KB (-19.6%). Both binaries built identically (cargo near build non-reproducible-wasm --features abi --profile=release-contract --locked, same wasm-opt -O post-step):

Raw bytes Gzipped
main (v3.13.0) 1,510,735 575,434
this PR 1,214,333 455,515
delta -296,402 (-19.6%) -119,919 (-20.8%)

cargo tree -p mpc-contract -i dcap-qvl returns no match on this branch (it resolves on main), confirming dcap-qvl is no longer in the contract's build graph. The crypto-verification weight moves to the already-merged tee-verifier contract.

`submit_participant_info` now offloads DCAP verification for `Dstack`
attestations to the standalone `tee-verifier` contract over a cross-contract
call, resolved through the yield-resume pattern; `Mock` attestations stay
synchronous. This drops `dcap-qvl` from the `mpc-contract` WASM.

- New `pending_attestations` state (one in-flight verification per account) and
  `FinalOutcome` (byte-pinned borsh layout, rides the yield-resume payload).
- `submit_dstack_attestation` yields and calls `verify_quote`; `resolve_verification`
  bridges the verifier response, runs the post-DCAP checks via `verify_with_report`,
  charges storage, and resumes. `on_attestation_verified` handles the yield timeout,
  cleaning up and refunding from a separate `fail_on_attestation_timeout` receipt.
- A failed storage charge in the committing callback receipt is reverted explicitly.
- `tee_verifier_account_id` stays `Option`; `None` rejects `Dstack` submits with
  `VerifierNotConfigured` (non-Option migration tracked in #3639).
- Drops `local-verify`/`dcap-qvl` from `mpc-contract`; contract dispatches via the
  post-DCAP-only `verify_with_report`.
- New `test-tee-verifier` stub + sandbox tests for the rejection, crash/timeout, and
  not-configured branches.

Closes #3642
Copilot AI review requested due to automatic review settings June 24, 2026 10:05
…ttestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the contract-side switch from in-WASM (sync) DCAP quote verification to an async cross-contract flow that calls a trusted tee-verifier contract, enabling mpc-contract to drop the dcap-qvl dependency and shrink its WASM. It introduces new pending-attestation state and callback plumbing to safely resume or timeout attestation submissions, plus a stub verifier contract and sandbox tests for key failure branches.

Changes:

  • Make submit_participant_info async for Dstack attestations (yield → verify_quote XCC → .then bridge → yield callback), while keeping Mock synchronous.
  • Add pending_attestations state and FinalOutcome wire type to arbitrate single-resume vs timeout cleanup and handle storage-charging/revert semantics in callback receipts.
  • Add a test-tee-verifier stub contract and sandbox tests covering “verifier not configured”, “rejected”, and “verifier crash/timeout” branches; update config/interface DTOs and regenerate ABI/schema snapshots.

Reviewed changes

Copilot reviewed 28 out of 29 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/design/attestation-verifier-contract.md Mark design as largely implemented and document remaining follow-ups.
crates/test-utils/src/contract_types.rs Extend dummy config builder with new verifier-related gas fields.
crates/test-tee-verifier/src/lib.rs Add a test-only stub verifier contract returning canned verify_quote outcomes.
crates/test-tee-verifier/Cargo.toml Define stub verifier crate features/deps for ABI/schema generation.
crates/near-mpc-contract-interface/src/types/config.rs Add new gas config fields to InitConfig/Config and extend serde tests.
crates/near-mpc-contract-interface/src/method_names.rs Add method-name constants for new attestation callbacks and verify_quote.
crates/mpc-attestation/src/attestation.rs Add verify_mock_only and update local-verify docs to reflect contract offloading.
crates/contract/tests/snapshots/abi__abi_has_not_changed.snap Update ABI snapshot for new methods/return type and config fields.
crates/contract/tests/sandbox/utils/mpc_contract.rs Add helpers for deposit-attached submit and has_pending_attestation view.
crates/contract/tests/sandbox/utils/contract_build.rs Add builder/caching for stub verifier WASM.
crates/contract/tests/sandbox/upgrade_from_current_contract.rs Update config proposal test data for new gas fields.
crates/contract/tests/sandbox/tee_verifier.rs Add sandbox tests for async verifier-not-configured, rejection refund, and timeout cleanup.
crates/contract/tests/sandbox/mod.rs Register new sandbox test module.
crates/contract/tests/sandbox/contract_configuration.rs Update init-config test to include new gas fields.
crates/contract/tests/inprocess/attestation_submission.rs Adjust in-process tests for PromiseOrValue<()> return on mock submissions.
crates/contract/src/v3_12_0_state.rs Initialize pending_attestations on migration into the new state.
crates/contract/src/tee/tee_state.rs Split sync mock path vs post-DCAP Dstack finishing; add explicit revert helper for async store.
crates/contract/src/tee/pending_attestation.rs Add PendingAttestation state + FinalOutcome with pinned Borsh layout tests.
crates/contract/src/tee.rs Export new pending_attestation module.
crates/contract/src/storage_keys.rs Add storage key for pending_attestations.
crates/contract/src/snapshots/mpc_contract__tests__mpc_contract_borsh_schema_has_not_changed.snap Update contract borsh schema snapshot for new config/state fields.
crates/contract/src/sandbox_test_methods.rs Add sandbox-only view has_pending_attestation.
crates/contract/src/lib.rs Implement async Dstack submission, resolve callback, yield callback/timeout failure, deposit refund + storage charging refactor.
crates/contract/src/errors.rs Add new TeeError variants for verifier-not-configured and already-pending verification.
crates/contract/src/dto_mapping.rs Map new config fields between interface DTOs and contract config.
crates/contract/src/config.rs Add defaults for verifier/callback gas attachments.
crates/contract/Cargo.toml Drop mpc-attestation local-verify feature usage; add verifier-interface schema feature and new deps.
Cargo.toml Add test-tee-verifier to workspace members/deps.
Cargo.lock Lockfile updates for new crate and updated dependency graph.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/contract/src/lib.rs
Comment thread crates/contract/src/lib.rs Outdated
Comment on lines +877 to +894
let (quote, collateral) = (dstack.quote.clone(), dstack.collateral.clone());
let attached_deposit = env::attached_deposit();
let tls_public_key = node_id.tls_public_key.clone();

self.enqueue_yield_request(
method_names::ON_ATTESTATION_VERIFIED,
borsh::to_vec(&account_id).expect("borsh serialization of account_id must succeed"),
Gas::from_tgas(self.config.on_attestation_verified_tera_gas),
|this, data_id| {
this.pending_attestations.insert(
account_id.clone(),
PendingAttestation {
dstack,
tls_public_key,
attached_deposit,
caller_is_not_participant,
data_id,
},
Comment thread crates/near-mpc-contract-interface/src/method_names.rs
pbeza added 5 commits June 24, 2026 12:47
- Rename `fail_on_attestation_timeout` to `fail_attestation_submission`: it is
  reached for every failure outcome (verifier rejection, post-DCAP failure, and
  yield timeout), not just timeouts, so the old name was misleading.
- Reorder `submit_dstack_attestation` so the detached `verify_quote` promise
  chain is built before `enqueue_yield_request`, keeping the latter's
  `promise_return` the final host call per its documented invariant. Behavior
  is unchanged; only statement order differs.
- Regenerate the ABI snapshot for the renamed method.
Order the `attestation` and `tee-verifier-interface` dependencies added for the
async verifier flow so `cargo sort --grouped` passes.
- `submit_participant_info` returns `Result<(), Error>` instead of
  `Result<PromiseOrValue<()>, Error>`, matching the `sign` / `ckd` /
  `verify_foreign_transaction` yield producers; `submit_dstack_attestation`
  ends on `enqueue_yield_request` so its `promise_return` is the final host
  call (resolves the "must be the last operation" invariant).
- Flesh out the `submit_participant_info` rustdoc: sync `Mock` vs async
  `Dstack`, the `VerifierNotConfigured` / `VerificationAlreadyPending` errors,
  and refund-on-failure behavior.
- `verify_mock_only`'s `Dstack` arm is `unreachable!()` (guaranteed-dead path).
- Clarify the `on_attestation_verified` gas-budget docstring (covers the
  heavier timeout branch).
- Serialize the verify_quote args by reference to avoid cloning the quote /
  collateral; read `tls_public_key` from the pending entry in
  `finish_verified_attestation` for rollback symmetry.
- Rename the sandbox tests to the `<sut>__should_<assertion>` form.
- Regenerate the ABI snapshot.

A Dstack rejection resolves in the verifier's response receipt (a later
receipt than the original call), so the outcome is asserted via contract state
rather than the original transaction's result.
The sandbox tests build the stub by manifest path via `ContractBuilder`, not as
a Cargo dependency, so the `[workspace.dependencies]` alias was never consumed
and `cargo shear` flagged it. The workspace member entry is kept so the crate is
still built and checked.
…ication

`resolve_verification` is public, so linking `[`Self::submit_dstack_attestation`]`
(a private fn) tripped `rustdoc::private_intra_doc_links` under `-D warnings`,
failing `cargo doc`. Refer to it by name instead.
@near near deleted a comment from claude Bot Jun 24, 2026
@near near deleted a comment from claude Bot Jun 24, 2026
@pbeza
pbeza requested a review from Copilot June 24, 2026 12:20
The doc-link fix changed `resolve_verification`'s rustdoc, which the ABI
captures in its `doc` field; regenerate the snapshot to match.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.

Comment thread crates/contract/src/lib.rs Outdated
Comment thread crates/mpc-attestation/src/attestation.rs Outdated
Comment thread crates/contract/src/lib.rs Outdated
pbeza added 5 commits June 24, 2026 15:00
- Drop the redundant `Attestation::verify_mock_only` wrapper: `add_mock_participant`
  already holds a `MockAttestation` and now calls `MockAttestation::verify`
  directly (the wrapper only round-tripped through the `Attestation` enum to match
  the Mock arm back out, and its `Dstack` arm was an unreachable panic).
- Reword the `InvalidAttestation` error prefix from "TeeQuoteStatus is invalid"
  to "attestation verification failed": the wrapped error is an
  `attestation::VerificationError` (allowlist / measurement / report-data checks),
  not a `TeeQuoteStatus`.
…ttestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract
The v3.13.0 release bumped existing crates' lockfile versions, but
test-tee-verifier is new on this branch and was still pinned at 3.12.0.
…ording

Replace bare-backtick code references in the async TEE attestation doc
comments with [`...`] intra-doc links where the item is linkable and plain
prose otherwise, so cargo doc catches drift instead of letting it rot
silently. Tighten the same comments.

Align the verifier-contract design doc with the shipped implementation
(Result<(), Error> return, Option<AccountId> verifier, separate
fail_attestation_submission receipt) and update the two TDX guides for the
renamed attestation-verification error string.
Drop four throwaway intermediate bindings flagged as redundant: the
millisecond temporary in current_time_seconds, and the let result; Ok(result)
tails in the three new sandbox test helpers (submit_participant_info_with_deposit,
has_pending_attestation, vote_tee_verifier_change). No behavior change.
@pbeza pbeza changed the title feat(contract): async TEE attestation verification via verifier contract, drop dcap-qvl feat(contract): async TEE attestation verification via verifier contract, drop dcap-qvl Jun 24, 2026
pbeza added 2 commits June 29, 2026 10:25
…ttestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract
…lone

`finish_verified_attestation` cloned `pending.dstack` (the TDX quote and
collateral buffers) into `finish_dstack_verify` even though verification only
ever borrows it: the owned value was wrapped in `Attestation::Dstack(_)` to
reach the `&self` `verify_with_report`, then dropped. Take `&DstackAttestation`
and call the `DstackVerify::verify` trait method directly on the borrow, so the
clone is gone and `resolve_verification`'s single-remove control flow is
untouched.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 2 comments.

Comment thread crates/contract/src/lib.rs Outdated
Comment on lines +2431 to +2433
let pending = self.pending_attestations.remove(&account_id).expect(
"checked contains_key above; no host call between mutates pending_attestations",
);
Comment on lines +13 to +16
//! The `Verified` + post-DCAP-pass path (attestation stored) additionally needs
//! a stub report matching the fixture's post-DCAP expectations; it is a planned
//! follow-up once the off-chain report helper is wired into the sandbox harness.
//! The post-DCAP logic itself is unit-tested in `mpc-attestation`.
pbeza added 2 commits June 29, 2026 13:04
The attestation flow resumed its yield with a Borsh-encoded `FinalOutcome`,
while the contract's other three yield-resume callbacks (sign, CKD, foreign-tx)
all use JSON. `FinalOutcome` is a private, internal payload that never leaves
`mpc-contract`, so there is no reason for it to differ. Switch it and
`on_attestation_verified`'s args to JSON, matching the existing convention.

The verifier-interface leg (`verify_quote` args/return, `VerificationResult`,
`resolve_verification`'s callback arg) stays Borsh: that is the cross-contract
wire format shared with external verifier callers, not the internal resume leg.
The TEE verifier vote storage keys already dropped their V1 suffix on this
branch; `PendingAttestationsV1` was the lone new key still carrying one. Rename
it to `PendingAttestations` so the keys added in this PR are consistent.

The borsh storage key derives from the enum variant's position, not its name,
and this is the last variant, so the on-chain key is unchanged.
pbeza added 14 commits June 29, 2026 14:10
`resolve_verification` looked up the same `pending_attestations` entry three
times (a `contains_key` guard, a `get().expect()` inside
`finish_verified_attestation`, and a trailing `remove().expect()`), with two
`expect()`s that only existed because the guard's presence guarantee was
invisible to the type system.

Remove the entry once, up front, into an owned binding via `let Some(...) else`
(the idiom the sibling yield flows use), and pass it by reference to
`finish_verified_attestation`. Three lookups collapse to one and both
data-presence `expect()`s are gone; behavior is unchanged. The no-verdict arm is
handled before the remove so the entry survives for the timeout path. The
remaining `expect()` on `serde_json::to_vec` is a genuine can't-fail invariant.
`FinalOutcome` said nothing about what it was the outcome of. Rename it to
`AttestationResult` to match the domain (it is the pass/fail result of an
attestation submission, returned to the caller) and the codebase's
operation-prefixed naming (`TeeValidationResult`, `SignatureResult`). The name
also avoids confusion with `tee_verifier_interface::VerificationResult`, the
verifier's Verified/Rejected answer that `resolve_verification` consumes one
line away.
… helper

Drop `map_attestation_submission_error` and make `AttestationSubmissionError` a
transparent `#[from]` variant of `Error`, matching every other domain error in
the contract (RespondError, TeeError, DomainError, ...). The call site uses `?`.
This also removes a double-prefixed message ("attestation verification failed:
the submitted attestation failed verification, ..."); the user-facing error is
now the transparent domain message.

Also use `String::to_string` over `.clone()` in the test verifier stub.
… docs

Flip `caller_is_not_participant` to `caller_is_participant` (a non-negated
boolean is easier to reason about), inverting its derivation and simplifying the
storage-charge guard from `!(is_new || not_participant)` to the positive
`caller_is_participant && !is_new_attestation`.

Also move the `tee_upgrade_deadline_duration` binding into the Mock arm that is
its only user (the Dstack path recomputes it at resolution time), revert the
unrelated `enqueue_yield_request` doc comment to match main, fix the
`pending_attestations` intra-doc link to the resolvable `crate::`-prefixed form,
and tighten the `submit_participant_info` and verifier-call comments.
The #[cfg(test)] add_participant helper only matched Attestation::Mock
through to add_mock_participant and panicked on Dstack, a branch no test
exercised. Delete it and have the tests call add_mock_participant
directly, passing the inner MockAttestation. Also tidy nearby doc
comments and inline a single-use binding in add_mock_participant.
store_verified_attestation and finish_dstack_verify returned
(ParticipantInsertion, Option<NodeAttestation>), but the enum was just
previous.is_some() re-encoded. Carry the overwritten entry inside the
UpdatedExistingParticipant variant so both return a single value, and
have revert_dstack_store recover it from there.
Tidy the async-attestation test code and docs:
- reuse test_tee_verifier::StubResponse instead of a hand-copied mirror
- collapse submit_participant_info into submit_participant_info_with_deposit
- parametrize the AttestationResult round-trip test with rstest
- import near_workspaces/wycheproof types instead of fully-qualified paths
- drop obvious comments and trim verbose docs; remove em dashes
- regenerate the ABI snapshot for the trimmed doc comments
…ttestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract
Depending on the test-tee-verifier #[near] contract crate as a Rust
dev-dependency broke 'cargo test --all-features': StubResponse's
abi-gated BorshSchema bound went unsatisfied and the two contracts'
__near_abi_contract_source_metadata symbols collided at link time.
Revert to the local wire-only mirror (the stub stays a WASM artifact)
and drop the dev-dependency.

Also turn the dangling intra-doc links in pending_attestation.rs (left
without their reference definitions after the module doc was shortened)
into prose, fixing the broken-intra-doc-links doc check.
The overwrite-rejection test asserted the pre-refactor
InvalidTeeRemoteAttestation error; this branch surfaces that rejection
as the dedicated AttestationSubmissionError::TlsKeyOwnedByOtherAccount
variant. Match the typed error and drop the now-unused InvalidParameters
import.
…ttestation-verification-through-the-verifier-contract-and-drop-dcap-qvl-from-mpc-contract
These two test files come from a separately-merged PR, not this branch.
They were edited during a branch-wide comment/import cleanup before main
was merged, so the changes were out of scope. Restore them to match main.
The attestation fail-promise borrowed fail_on_timeout_tera_gas, a config
field named for the sign/CKD/foreign-tx timeout path. Add a dedicated
fail_attestation_submission_tera_gas (default 2 Tgas, the same trivial
panic cost) so the budget matches the method it funds and tuning one no
longer silently affects the other. Threaded through the interface DTO,
Config, dto_mapping, defaults, and test configs; ABI and borsh-schema
snapshots regenerated.
@pbeza

pbeza commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

JFYI for anyone tracking this PR: I’ll split it into two smaller PRs, since I don’t expect reviewers to go through this much code at once:

pbeza added a commit that referenced this pull request Jul 3, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 13, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 14, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 14, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 16, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 16, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 16, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
pbeza added a commit that referenced this pull request Jul 18, 2026
StubResponse was declared twice (stub contract + test mirror) kept
aligned by a KEEP-IN-SYNC comment and a discriminant-pinning test,
because importing the #[near] stub crate as a dep breaks
cargo test --all-features (duplicate contract-ABI symbol + abi-feature
unification; see PR #3664).

Extract it into a new plain-lib crate test-tee-verifier-types that both
the stub and the contract's test binary depend on. A non-#[near] crate
emits no contract-ABI symbol, so it can be a dev-dep of mpc-contract
without the collision, giving a real single source of truth: the mirror,
the sync comment, and the stub_response_discriminants test are removed.

Verified in nix: cargo test --no-run --all-features -p mpc-contract
links cleanly (the step that regressed in #3664), and the sandbox
tee_verifier suite passes driven through the shared type.
@gilcu3

gilcu3 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

superseded by #3714

@gilcu3 gilcu3 closed this Jul 23, 2026
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.

Wire async TEE attestation verification through the verifier contract and drop dcap-qvl from mpc-contract

3 participants