Skip to content

Commit cf27fef

Browse files
committed
test(contract): store the Verified attestation cross-contract in sandbox
Un-ignores the store-path tests now that the fixture keypair is complete: a Verified quote stores through the real deployed verifier, and the TlsKeyOwnedByOtherAccount guard is exercised across the promise chain by two accounts sharing the fixture key. They deploy the wasm built with sandbox-test-attestation, since the fixture's app-compose carries a pre-launch script. Drops the planned out-of-gas test for resolve_verification: near-sdk forwards unused prepaid gas to the callback, so the callback cannot be starved by lowering resolve_verification_tera_gas while the caller attaches max gas. The config is a floor, not a cap.
1 parent 23b1490 commit cf27fef

3 files changed

Lines changed: 46 additions & 47 deletions

File tree

crates/contract/tests/sandbox/common.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ impl SandboxTestSetup {
182182
number_of_participants: PARTICIPANT_LEN,
183183
init_config: None,
184184
with_sandbox_test_methods: false,
185+
with_sandbox_test_attestation: false,
185186
}
186187
}
187188

@@ -200,6 +201,7 @@ pub struct SandboxTestSetupBuilder {
200201
number_of_participants: usize,
201202
init_config: Option<dtos::InitConfig>,
202203
with_sandbox_test_methods: bool,
204+
with_sandbox_test_attestation: bool,
203205
}
204206

205207
impl SandboxTestSetupBuilder {
@@ -231,9 +233,23 @@ impl SandboxTestSetupBuilder {
231233
self
232234
}
233235

236+
/// Deploys the wasm built with `--features sandbox-test-attestation`, which accepts the
237+
/// attestation fixture's app-compose. Required by tests that submit the Dstack fixture
238+
/// and expect it to verify.
239+
pub fn with_sandbox_test_attestation(mut self) -> Self {
240+
self.with_sandbox_test_attestation = true;
241+
self
242+
}
243+
234244
pub async fn build(self) -> SandboxTestSetup {
245+
assert!(
246+
!(self.with_sandbox_test_methods && self.with_sandbox_test_attestation),
247+
"no wasm is built with both test feature sets; add one if a test needs it"
248+
);
235249
let (worker, contract) = if self.with_sandbox_test_methods {
236250
init_with_wasm(contract_build::current_contract_with_sandbox_test_methods()).await
251+
} else if self.with_sandbox_test_attestation {
252+
init_with_wasm(contract_build::current_contract_with_sandbox_test_attestation()).await
237253
} else {
238254
init().await
239255
};

crates/contract/tests/sandbox/tee_verifier.rs

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
//! time is wall-clock and forward-only, and the fixture collateral has
99
//! expired against it.
1010
//!
11-
//! Verified-path tests that store an attestation must sign as the fixture
12-
//! account (the quote's report_data binds the fixture account key, and the
13-
//! contract reads that key from the transaction signer). They are ignored
14-
//! until the fixture secret key asset lands; see TODO(#3787).
11+
//! Verified-path tests that store an attestation sign as the fixture account:
12+
//! the quote's report_data binds the fixture account key, and the contract
13+
//! reads that key from the transaction signer.
1514
#![allow(non_snake_case)]
1615

1716
use crate::sandbox::{
@@ -53,6 +52,16 @@ async fn setup() -> SandboxTestSetup {
5352
.await
5453
}
5554

55+
/// Setup for tests that expect the fixture to pass the post-DCAP checks, which needs the
56+
/// wasm that accepts its app-compose.
57+
async fn setup_accepting_fixture_attestation() -> SandboxTestSetup {
58+
SandboxTestSetup::builder()
59+
.with_protocols(ALL_PROTOCOLS)
60+
.with_sandbox_test_attestation()
61+
.build()
62+
.await
63+
}
64+
5665
/// Votes `verifier` in as `mpc-contract`'s trusted verifier (all participants vote
5766
/// so the change crosses threshold).
5867
async fn trust_verifier(contract: &Contract, participants: &[Account], verifier: &AccountId) {
@@ -418,15 +427,14 @@ async fn submit_participant_info__should_fail_cleanly_when_verifier_gas_budget_t
418427
}
419428

420429
#[tokio::test]
421-
#[ignore = "TODO(#3787): requires the near_account_secret_key asset"]
422430
async fn submit_participant_info__should_store_attestation_on_verified_quote() {
423431
// Given
424432
let SandboxTestSetup {
425433
worker,
426434
mpc_signer_accounts,
427435
contract,
428436
..
429-
} = setup().await;
437+
} = setup_accepting_fixture_attestation().await;
430438
deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await;
431439
whitelist_fixture_dstack_measurements(&contract, &mpc_signer_accounts).await;
432440
let submitter = create_fixture_account(&worker, "fixture-node-a").await;
@@ -461,46 +469,6 @@ async fn submit_participant_info__should_store_attestation_on_verified_quote() {
461469
}
462470

463471
#[tokio::test]
464-
#[ignore = "TODO(#3787): requires the near_account_secret_key asset"]
465-
async fn submit_participant_info__should_fail_and_store_nothing_when_resolve_verification_runs_out_of_gas()
466-
{
467-
// Given: a callback budget far below the ~20 Tgas the post-DCAP work needs,
468-
// but enough to schedule the callback receipt. Reaching that gas-heavy path
469-
// requires a Verified verdict and a submitter holding the fixture key.
470-
let SandboxTestSetup {
471-
worker,
472-
mpc_signer_accounts,
473-
contract,
474-
..
475-
} = SandboxTestSetup::builder()
476-
.with_protocols(ALL_PROTOCOLS)
477-
.with_init_config(dtos::InitConfig {
478-
resolve_verification_tera_gas: Some(3),
479-
..Default::default()
480-
})
481-
.build()
482-
.await;
483-
deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await;
484-
whitelist_fixture_dstack_measurements(&contract, &mpc_signer_accounts).await;
485-
let submitter = create_fixture_account(&worker, "fixture-node-a").await;
486-
let balance_before = submitter.view_account().await.unwrap().balance;
487-
488-
// When
489-
let result = submit_dstack(&submitter, &contract).await;
490-
491-
// Then: the callback receipt rolls back, so nothing may be stored.
492-
assert_submission_failed_cleanly(
493-
&result,
494-
&contract,
495-
&submitter,
496-
balance_before,
497-
"Exceeded the prepaid gas",
498-
)
499-
.await;
500-
}
501-
502-
#[tokio::test]
503-
#[ignore = "TODO(#3787): requires the near_account_secret_key asset"]
504472
async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owned_by_other_account()
505473
{
506474
// Given: an owner stored a Verified attestation for the fixture TLS key.
@@ -513,7 +481,7 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne
513481
mpc_signer_accounts,
514482
contract,
515483
..
516-
} = setup().await;
484+
} = setup_accepting_fixture_attestation().await;
517485
deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await;
518486
whitelist_fixture_dstack_measurements(&contract, &mpc_signer_accounts).await;
519487
let owner = create_fixture_account(&worker, "fixture-node-a").await;

crates/contract/tests/sandbox/utils/contract_build.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ const TEE_VERIFIER_MANIFEST: &str = "crates/tee-verifier/Cargo.toml";
88
const MPC_CONTRACT_OUT_DIR: &str = "target/near/contract-noabi";
99
const MPC_CONTRACT_BENCH_OUT_DIR: &str = "target/near/contract-noabi-bench";
1010
const MPC_CONTRACT_SANDBOX_OUT_DIR: &str = "target/near/contract-noabi-sandbox";
11+
const MPC_CONTRACT_ATTESTATION_OUT_DIR: &str = "target/near/contract-noabi-attestation";
1112
const TEE_VERIFIER_SANDBOX_OUT_DIR: &str = "target/near/tee-verifier-sandbox";
1213

1314
static CONTRACT: OnceLock<Vec<u8>> = OnceLock::new();
1415
static CONTRACT_WITH_BENCH_METHODS: OnceLock<Vec<u8>> = OnceLock::new();
1516
static CONTRACT_WITH_SANDBOX_TEST_METHODS: OnceLock<Vec<u8>> = OnceLock::new();
17+
static CONTRACT_WITH_SANDBOX_TEST_ATTESTATION: OnceLock<Vec<u8>> = OnceLock::new();
1618
static MIGRATION_CONTRACT: OnceLock<Vec<u8>> = OnceLock::new();
1719
static PARALLEL_CONTRACT: OnceLock<Vec<u8>> = OnceLock::new();
1820
static TEE_VERIFIER_CONTRACT: OnceLock<Vec<u8>> = OnceLock::new();
@@ -51,6 +53,19 @@ pub fn current_contract_with_sandbox_test_methods() -> &'static [u8] {
5153
})
5254
}
5355

56+
/// Returns the current contract WASM that accepts the attestation fixture's app-compose.
57+
/// Use this only for tests that submit the Dstack fixture and need it to verify: the
58+
/// fixture carries the `pre_launch_script` that exported its signer key, which the
59+
/// production policy rejects.
60+
pub fn current_contract_with_sandbox_test_attestation() -> &'static [u8] {
61+
CONTRACT_WITH_SANDBOX_TEST_ATTESTATION.get_or_init(|| {
62+
ContractBuilder::new(MPC_CONTRACT_MANIFEST)
63+
.out_dir(MPC_CONTRACT_ATTESTATION_OUT_DIR)
64+
.features(&["sandbox-test-attestation"])
65+
.build()
66+
})
67+
}
68+
5469
pub fn migration_contract() -> &'static [u8] {
5570
MIGRATION_CONTRACT.get_or_init(|| ContractBuilder::new(MIGRATION_CONTRACT_MANIFEST).build())
5671
}

0 commit comments

Comments
 (0)