Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
99f6904
feat(contract): auto-expire unused launcher image hashes
barakeinav1 Jun 15, 2026
d7c0c65
fix(contract): validate config TTL on init, dedup dummy_config value
barakeinav1 Jul 2, 2026
a8694aa
docs(contract): clarify overflow, re-vote, and capability-token behavior
barakeinav1 Jul 2, 2026
cb955fb
docs: correct attestation validity window (1 day, not 7) in comments …
barakeinav1 Jul 2, 2026
074a701
Merge branch 'main' into feat/auto-remove-launcher-hashes
barakeinav1 Jul 5, 2026
c435dc5
refactor(contract): collapse launcher timestamps to single last_used;…
barakeinav1 Jul 7, 2026
9759f11
style: rustfmt the enlarging_ttl test
barakeinav1 Jul 7, 2026
d329413
refactor(contract): add_or_refresh returns AddOutcome; sync design do…
barakeinav1 Jul 8, 2026
13fbc1f
Merge branch 'main' into feat/auto-remove-launcher-hashes
barakeinav1 Jul 9, 2026
6e3039e
docs(contract): compact refresh-on-use comment; TODO for 3.13.0 migra…
barakeinav1 Jul 9, 2026
096dfb1
docs(contract): drop broken public->private intra-doc link on AddOutcome
barakeinav1 Jul 9, 2026
d725003
Merge branch 'main' into feat/auto-remove-launcher-hashes
barakeinav1 Jul 9, 2026
e80673a
Merge remote-tracking branch 'origin/main' into feat/auto-remove-laun…
barakeinav1 Jul 12, 2026
07de77b
refactor(contract): address review nits on launcher image handling
barakeinav1 Jul 12, 2026
2aa024e
refactor(contract): log on is_expired overflow; fix stale 'added' tes…
barakeinav1 Jul 12, 2026
c95e32d
docs(contract): drop public->private intra-doc link on AllowedLaunche…
barakeinav1 Jul 13, 2026
e1d8955
Merge branch 'main' into feat/auto-remove-launcher-hashes
barakeinav1 Jul 15, 2026
04254ac
Merge remote-tracking branch 'origin/main' into feat/auto-remove-laun…
barakeinav1 Jul 20, 2026
37c0218
docs(contract): drop/shorten comments that restate the code
barakeinav1 Jul 21, 2026
eb593e5
test: add add_participant_no_expiry helper; trim two more comments
barakeinav1 Jul 22, 2026
df57fd8
Merge remote-tracking branch 'origin/main' into feat/auto-remove-laun…
barakeinav1 Jul 22, 2026
4485904
fix(contract): apply launcher expiry + refresh to WithConstraints mocks
barakeinav1 Jul 23, 2026
3fc93c7
Merge remote-tracking branch 'origin/main' into feat/auto-remove-laun…
barakeinav1 Jul 28, 2026
883dfad
Address claude[bot] review: docs, tests, and small cleanups
barakeinav1 Jul 28, 2026
797407a
test: add assert_matches exemption comments for PromiseOrValue
barakeinav1 Jul 28, 2026
6ffd125
test: mock-path participant gate — non-participant submission does no…
barakeinav1 Jul 28, 2026
1748925
Merge remote-tracking branch 'origin/main' into feat/auto-remove-laun…
barakeinav1 Jul 30, 2026
02a05c3
refactor(contract): store launcher expires_at; address review comments
barakeinav1 Jul 30, 2026
503a627
test(migration): cover the combined 3.13.0 migration path
barakeinav1 Jul 30, 2026
9cf1bd1
docs(design): update design doc to the expires_at model
barakeinav1 Jul 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/contract/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,8 @@ These functions require the caller to be a participant or candidate.
| `version()` | Returns the contract version. | `String` | TBD | TBD |
| `update_config(config: ConfigV1)` | Updates the contract configuration for `V1`. | `()` | TBD | TBD |
| `allowed_docker_image_hashes()` | Returns all currently allowed MPC Docker image hashes with their eviction expiry, newest first. | `Vec<AllowedMpcDockerImageHash>` | TBD | TBD |
| `allowed_launcher_image_hashes()` | Returns all currently allowed launcher image hashes. | `Vec<LauncherImageHash>` | TBD | TBD |
| `allowed_launcher_compose_hashes()` | Returns all currently allowed launcher compose hashes (derived from launcher + MPC image pairs). | `Vec<LauncherDockerComposeHash>` | TBD | TBD |
| `allowed_launcher_image_hashes()` | Returns the non-expired allowed launcher image hashes (the most-recently-used entry only when all are expired). | `Vec<LauncherImageHash>` | TBD | TBD |
| `allowed_launcher_compose_hashes()` | Returns the non-expired allowed launcher compose hashes (derived from launcher + MPC image pairs; the most-recently-used entry only when all are expired). | `Vec<LauncherDockerComposeHash>` | TBD | TBD |
| `launcher_hash_votes()` | Returns current launcher hash votes, showing each participant's vote. | `LauncherHashVotes` | TBD | TBD |
| `code_hash_votes()` | Returns current code hash votes, showing each participant's vote. | `CodeHashesVotes` | TBD | TBD |
| `allowed_os_measurements()` | Returns all currently allowed OS measurement sets. | `Vec<ContractExpectedMeasurements>` | TBD | TBD |
Expand Down
25 changes: 25 additions & 0 deletions crates/contract/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const DEFAULT_VERIFIER_TERA_GAS: u64 = 200;
/// Prepaid gas for the `resolve_verification` callback. Carries the bulk of the
/// post-DCAP work (allowlist match, RTMR3 replay, app-compose validation, store).
const DEFAULT_RESOLVE_VERIFICATION_TERA_GAS: u64 = 60;
/// Default TTL after which a launcher image hash unused by any participant is evicted.
const DEFAULT_LAUNCHER_HASH_UNUSED_TTL_SECONDS: u64 = 14 * 24 * 60 * 60; // 14 days
/// Prepaid gas for a `clean_expired_launcher_hashes` call.
const DEFAULT_CLEAN_EXPIRED_LAUNCHER_HASHES_TERA_GAS: u64 = 5;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Why 5 TGas: this is the budget for the detached, #[private] clean_expired_launcher_hashes self-call spawned from verify_tee (physical eviction of launcher hashes past their TTL).

Measured via a sandbox (near-workspaces) benchmark: the call burns ~3.0 TGas (function-call receipt) / ~3.35 TGas total on a small allowlist. The cost is dominated by contract state load/store + the base function-call charge, not the launcher count (the eviction loop over a handful of operator-curated entries is negligible), so it stays flat as the allowlist changes. That leaves ~40% headroom under 5 TGas.

It's also consistent with the sibling detached-cleanup budgets that do comparable small work (clean_foreign_chain_data, remove_non_participant_* are all 5), and it's fail-safe: the call is detached, so a shortfall can't fail verify_tee, and expiry is already enforced at read time — physical eviction is just GC that retries next round. Tunable via Config if a benchmark on production-sized state ever warrants it.


/// Config for V2 of the contract.
#[near(serializers=[borsh, json])]
Expand Down Expand Up @@ -81,6 +85,10 @@ pub(crate) struct Config {
pub(crate) verifier_tera_gas: u64,
/// Prepaid gas for the `resolve_verification` callback.
pub(crate) resolve_verification_tera_gas: u64,
/// TTL after which a launcher image hash unused by any participant is evicted.
pub(crate) launcher_hash_unused_ttl_seconds: u64,

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.

I see no test covering enlarging the launcher_hash_unused_ttl_seconds config while entries are stored: a bigger TTL should bring back an entry a smaller TTL had hidden, since filtering only hides (doesn't delete — only cleanup_expired does). Existing tests only advance time at a fixed TTL.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I see no test covering enlarging the launcher_hash_unused_ttl_seconds ... a bigger TTL should bring back an entry a smaller TTL had hidden

Good point — added enlarging_ttl_unhides_previously_expired_entry in c435dc5, asserting a larger TTL re-surfaces an entry a smaller TTL hid (filtering hides, only cleanup_expired deletes).

/// Prepaid gas for a `clean_expired_launcher_hashes` call.
pub(crate) clean_expired_launcher_hashes_tera_gas: u64,
}

impl Default for Config {
Expand Down Expand Up @@ -110,6 +118,23 @@ impl Default for Config {
DEFAULT_REMOVE_NON_PARTICIPANT_TEE_VERIFIER_VOTES_TERA_GAS,
verifier_tera_gas: DEFAULT_VERIFIER_TERA_GAS,
resolve_verification_tera_gas: DEFAULT_RESOLVE_VERIFICATION_TERA_GAS,
launcher_hash_unused_ttl_seconds: DEFAULT_LAUNCHER_HASH_UNUSED_TTL_SECONDS,
clean_expired_launcher_hashes_tera_gas: DEFAULT_CLEAN_EXPIRED_LAUNCHER_HASHES_TERA_GAS,
}
}
}

impl Config {
/// Invariant: a launcher hash backing a still-valid attestation must never expire,
/// so its unused-TTL must be at least the attestation validity window.
Comment thread
SimonRastikian marked this conversation as resolved.
pub(crate) fn validate(&self) -> Result<(), &'static str> {
if self.launcher_hash_unused_ttl_seconds
< mpc_attestation::attestation::DEFAULT_EXPIRATION_DURATION_SECONDS
{
return Err(
"launcher_hash_unused_ttl_seconds must be >= DEFAULT_EXPIRATION_DURATION_SECONDS",
);
}
Ok(())
}
}
10 changes: 10 additions & 0 deletions crates/contract/src/dto_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ impl From<near_mpc_contract_interface::types::InitConfig> for Config {
if let Some(v) = config_ext.resolve_verification_tera_gas {
config.resolve_verification_tera_gas = v;
}
if let Some(v) = config_ext.launcher_hash_unused_ttl_seconds {
config.launcher_hash_unused_ttl_seconds = v;
}
if let Some(v) = config_ext.clean_expired_launcher_hashes_tera_gas {
config.clean_expired_launcher_hashes_tera_gas = v;
}

config
}
Expand Down Expand Up @@ -533,6 +539,8 @@ impl From<&Config> for near_mpc_contract_interface::types::Config {
.remove_non_participant_tee_verifier_votes_tera_gas,
verifier_tera_gas: value.verifier_tera_gas,
resolve_verification_tera_gas: value.resolve_verification_tera_gas,
launcher_hash_unused_ttl_seconds: value.launcher_hash_unused_ttl_seconds,
clean_expired_launcher_hashes_tera_gas: value.clean_expired_launcher_hashes_tera_gas,
}
}
}
Expand Down Expand Up @@ -564,6 +572,8 @@ impl From<near_mpc_contract_interface::types::Config> for Config {
.remove_non_participant_tee_verifier_votes_tera_gas,
verifier_tera_gas: value.verifier_tera_gas,
resolve_verification_tera_gas: value.resolve_verification_tera_gas,
launcher_hash_unused_ttl_seconds: value.launcher_hash_unused_ttl_seconds,
clean_expired_launcher_hashes_tera_gas: value.clean_expired_launcher_hashes_tera_gas,
}
}
}
Expand Down
Loading