Skip to content

Commit d1e513b

Browse files
committed
refactor(tee-verifier): return Result via #[handle_result], move error out of the wire crate
verify_quote now returns Result<VerifiedReport, VerifierError> with #[handle_result] instead of returning a bare value and calling env::panic_str directly. Behaviour is unchanged (an Err still panics, surfacing to a cross-contract caller as PromiseError::Failed), but the fallible-method shape matches the rest of the contract surface and the error message now comes from the error's Display. VerifierError moves from tee-verifier-interface into tee-verifier: it never crosses the wire (failures panic rather than serialize a returned error), so it does not belong in the DTO crate. tee-verifier-interface drops its thiserror dependency and keeps only the genuine wire types; tee-verifier picks thiserror up and implements FunctionError on the local error.
1 parent 5fae5d5 commit d1e513b

6 files changed

Lines changed: 26 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tee-verifier-interface/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ borsh-schema = ["borsh/unstable__schema"]
1010

1111
[dependencies]
1212
borsh = { workspace = true }
13-
thiserror = { workspace = true }
1413

1514
[dev-dependencies]
1615
rstest = { workspace = true }

crates/tee-verifier-interface/src/lib.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,6 @@ pub struct Collateral {
6262
pub pck_certificate_chain: Option<String>,
6363
}
6464

65-
/// Errors returned by `tee-verifier`'s `verify_quote` method.
66-
///
67-
/// Borsh-stable. Mirrors what `dcap_qvl::verify::verify` would otherwise
68-
/// surface to the caller, plus room for verifier-side failures.
69-
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, thiserror::Error)]
70-
#[cfg_attr(feature = "borsh-schema", derive(borsh::BorshSchema))]
71-
pub enum VerifierError {
72-
/// `dcap_qvl::verify::verify` rejected the quote / collateral. The string
73-
/// is the upstream error rendered with `Display`.
74-
#[error("dcap verification failed: {0}")]
75-
DcapVerification(String),
76-
}
77-
7865
/// Verified TDX / SGX quote, mirroring `dcap_qvl::verify::VerifiedReport`.
7966
///
8067
/// All fields match the upstream type one-to-one. Borsh-stable.
@@ -257,22 +244,6 @@ mod tests {
257244
assert_eq!(original, decoded);
258245
}
259246

260-
#[test]
261-
fn verifier_error__should_round_trip_borsh() {
262-
// Given
263-
let original = VerifierError::DcapVerification(String::from("bad signature"));
264-
265-
// When
266-
let bytes = borsh::to_vec(&original).expect("Borsh serialization should succeed");
267-
let decoded: VerifierError =
268-
borsh::from_slice(&bytes).expect("Borsh deserialization should succeed");
269-
270-
// Then
271-
match decoded {
272-
VerifierError::DcapVerification(msg) => assert_eq!(msg, "bad signature"),
273-
}
274-
}
275-
276247
#[test]
277248
fn report__as_td10__should_unwrap_td15_to_its_base() {
278249
// Given

crates/tee-verifier/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ borsh = { workspace = true }
3939
dcap-qvl = { workspace = true }
4040
near-sdk = { workspace = true }
4141
tee-verifier-interface = { workspace = true }
42+
thiserror = { workspace = true }
4243

4344
[target.'cfg(target_arch = "wasm32")'.dependencies]
4445
getrandom = { workspace = true, features = ["custom"] }

crates/tee-verifier/src/lib.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,25 @@
88
//!
99
//! See `docs/design/attestation-verifier-contract.md` for the design.
1010
11-
use near_sdk::{env, near};
11+
use near_sdk::{FunctionError, env, near};
1212
use tee_verifier_interface::{Collateral, QuoteBytes, VerifiedReport};
1313

1414
mod conversions;
1515

16+
/// Failure returned by [`TeeVerifier::verify_quote`].
17+
#[derive(Debug, Clone, thiserror::Error)]
18+
pub enum VerifierError {
19+
/// `dcap_qvl::verify::verify` rejected the quote / collateral.
20+
#[error("dcap verification failed: {0}")]
21+
DcapVerification(String),
22+
}
23+
24+
impl FunctionError for VerifierError {
25+
fn panic(&self) -> ! {
26+
env::panic_str(&self.to_string())
27+
}
28+
}
29+
1630
// `dcap-qvl`'s `contract` feature pulls in `getrandom` but doesn't enable
1731
// any backend. On `wasm32-unknown-unknown` we register a custom impl that
1832
// returns `UNSUPPORTED`. Quote verification should not draw any randomness;
@@ -30,30 +44,24 @@ pub struct TeeVerifier {}
3044

3145
#[near]
3246
impl TeeVerifier {
33-
/// Verify a TDX / SGX quote against Intel collateral.
47+
/// Verify a TDX quote against Intel collateral.
3448
///
3549
/// Calls `dcap_qvl::verify::verify` with the current block timestamp
3650
/// and returns the parsed `VerifiedReport` on success. The caller is
3751
/// responsible for any post-DCAP policy (RTMR3 replay, report-data
3852
/// binding, measurement allowlist matching, etc.).
39-
///
40-
/// On verification failure, panics with the upstream error rendered as
41-
/// a string. Callers should treat this as a `PromiseResult::Failed` in
42-
/// their callback.
43-
///
44-
/// Borsh I/O on both arguments and return value.
53+
#[handle_result]
4554
#[result_serializer(borsh)]
4655
pub fn verify_quote(
4756
&self,
4857
#[serializer(borsh)] quote: QuoteBytes,
4958
#[serializer(borsh)] collateral: Collateral,
50-
) -> VerifiedReport {
59+
) -> Result<VerifiedReport, VerifierError> {
5160
let now_seconds = env::block_timestamp_ms() / 1000;
5261
let quote_bytes = conversions::quote_bytes_to_vec(quote);
5362
let collateral = conversions::collateral_to_dcap(collateral);
54-
match dcap_qvl::verify::verify(&quote_bytes, &collateral, now_seconds) {
55-
Ok(report) => conversions::verified_report(report),
56-
Err(err) => env::panic_str(&format!("dcap verification failed: {err:?}")),
57-
}
63+
dcap_qvl::verify::verify(&quote_bytes, &collateral, now_seconds)
64+
.map(conversions::verified_report)
65+
.map_err(|err| VerifierError::DcapVerification(format!("{err:?}")))
5866
}
5967
}

crates/tee-verifier/tests/verify_quote.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ fn verify_quote__should_return_up_to_date_td10_report_for_valid_fixture() {
5555
let collateral = make_collateral();
5656

5757
// When
58-
let report = contract.verify_quote(quote, collateral);
58+
let report = contract
59+
.verify_quote(quote, collateral)
60+
.expect("valid fixture should verify");
5961

6062
// Then
6163
assert_eq!(report.status, "UpToDate");

0 commit comments

Comments
 (0)