Skip to content

feat: Phala TDX attestation trust-root for agent-challenge (validator/master, offline-validated)#39

Draft
echobt wants to merge 12 commits into
mainfrom
mission/phala-attest
Draft

feat: Phala TDX attestation trust-root for agent-challenge (validator/master, offline-validated)#39
echobt wants to merge 12 commits into
mainfrom
mission/phala-attest

Conversation

@echobt

@echobt echobt commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Base-side (validator / master) integration for the Phala TEE (Intel TDX) attestation-rooted agent-challenge evaluation. This is the trust-root half of the cross-repo change whose miner/enclave half lives in BaseIntelligence/agent-challenge (branch mission/phala-attest, available after PR merge).

What's included (offline-validated)

  • ExecutionProof Phala tier (src/base/schemas/worker.py, src/base/worker/proof.py) — new attestation payload {tdx_quote, event_log, report_data, measurement{mrtd,rtmr0-3,compose_hash,os_image_hash}, vm_config} + single-source phala_report_data binding (tag base-agent-challenge-v1). Existing tier-0/1/2 behavior unchanged.
  • Phala quote verifier (src/base/worker/phala_quote.py, phala_verify.py) — TDX quote parse, RTMR3 event-log replay, DCAP verify with park-vs-reject split; MeasurementAllowlist (fail-closed on empty, multi-entry image rotation, fail-closed loaders). verify_execution_proof extended with a conjunctive Phala path (attestation as trust root; nonce consumed last so a park never burns it).
  • Validator adapterrebind_worker_signature replaces the lean-image placeholder signature when ingesting the attested result.
  • Master R=1 — attested agent-challenge units stay at replication factor 1 with no worker-plane replication / reconciliation / dispute / audit (proven non-vacuous against a sibling GPU unit that replicates to R=2).
  • Flag-off invariant — legacy validator-run path byte-identical; the Phala verifier is never invoked when the flag is off.
  • Cross-integration / cross-compat tests — attestation carry-chain byte-integrity across the challenge↔base JSON boundary; a shared golden TDX quote/measurement vector asserted in both repos to catch cross-repo parser drift.

Validation

uv run pytest (with BASE_TEST_DATABASE_URL), uv run mypy src tests, and ruff all clean; per-milestone scrutiny + user-testing gates passed. Base test suite green (~1860 passed).

Pending: live TDX validation

Live verification of a real TDX quote against a deployed CVM is pending the live infrastructure described in the companion agent-challenge PR (registry, public RA-TLS-fronted key-release ingress, LLM gateway).

Note: this branch is currently ~2 commits behind origin/main; a merge/rebase may be needed before final merge.


Draft PR. Commits authored as echobt.

echobt added 12 commits July 8, 2026 10:35
Add the foundational Phala tier to the shared ExecutionProof envelope so the
image emitter (M1) and validator/master verifier (M4) share one canonical
schema (architecture.md sec 6/9):

- schemas/worker.py: PHALA_TDX_TIER constant ('phala-tdx'); PhalaMeasurement
  (mrtd, rtmr0-3, compose_hash, os_image_hash) with canonical() static subset;
  PhalaAttestation payload (tdx_quote, event_log, report_data, measurement,
  vm_config) accepting the tdx_quote_b64/report_data_hex aliases. Widen
  ExecutionProof.tier to int | str so it carries the Phala value; tier 0/1/2
  behavior is unchanged.
- worker/proof.py: phala_report_data / phala_report_data_hex (sec-6 binding,
  sorted task_ids, rtmr3 excluded, 64-byte left-aligned field) and
  build_phala_execution_proof (reuses build_execution_proof; keeps the tier-0
  worker signature so verify_execution_proof still validates it).

No fork of the envelope; quote verification is layered on later (M4).
Assert phala_report_data/_hex against a fixed input -> expected 64-byte hex
that agent-challenge's self-contained sec-6 replica asserts against too, so the
two implementations cannot silently drift (VAL-IMG-012).
Validate the exact attested-result envelope the agent-challenge canonical image
emits against base's real ExecutionProof/PhalaAttestation models, and assert
per-field omission is rejected. Drift guard for VAL-IMG-025/026 (mirrors the
report_data golden-vector pin).
… test

Correct the type: ignore code from [union-attr] to [attr-defined] on the
GOLDEN_EMITTED_ENVELOPE['attestation'].items() access; mypy infers the value
as object (attr-defined), so the milestone typecheck gate (uv run mypy src tests)
was failing. No behavior change.
… reject tamper, park on outage)

Extend verify_execution_proof with a Phala-tier verifier (VAL-VERIFY-001..014):
DCAP sig/TCB via QuoteVerifier (dcap-qvl), measurement reconstructed from the
signed quote + event-log RTMR3 replay checked against a validator-owned
allowlist, report_data bound to the validator's expected (agent_hash,
sorted task_ids, scores_digest, fresh single-use nonce), and tier-0 worker
signature still enforced (no cross-unit replay). A transient verifier outage
raises VerifierUnavailableError so the caller parks (never accepts, never
fraud-rejects). The agent_challenge adapter rebinds the lean image's placeholder
worker_signature to the ingesting unit; trust root remains the attestation.
…TDX quote golden vector

M4 verify-weights scrutiny robustness follow-ups (phala_quote.py):

1. DcapQvlVerifier.verify: a returncode==0 invocation whose stdout is
   unparseable / non-JSON / missing a TCB status is a dcap-qvl *tooling*
   regression, not a fraud verdict. Map it to VerifierUnavailableError (PARK,
   retryable) instead of QuoteVerificationError (permanent reject), so a tooling
   regression cannot permanently fraud-reject a legitimate result. Genuine
   invalid-quote/bad-TCB (nonzero exit) still permanently rejects; timeout /
   missing-binary / subprocess error still parks. Never accept-any.

2. Cross-repo anti-drift: pin a shared golden TDX quote/measurement/RTMR3 vector
   (fixed quote + event-log bytes -> expected MRTD/RTMR0-3/os_image_hash/RTMR3
   compose-hash) as a byte-identical fixture asserted here and in agent-challenge
   (tests/test_quote_golden_vector.py). A one-sided offset/hash tweak to either
   parser diverges from the pinned values and fails a test on that side.
…rity

Offline complements to the agent-challenge cross-integration suite: the
master keeps attested agent-challenge units at replication factor 1 with no
worker-plane reconcile (a sibling prism gpu unit still replicates to R=2,
so the result is non-vacuous), and the TDX quote/report_data/measurement
survive the challenge<->BASE JSON boundary and validator tier-0 rebind
byte-for-byte (a single flipped byte / re-encoded report_data breaks it).
Uses a deterministic in-test signer to keep bittensor's import-time logging
reconfiguration out of the module. Covers VAL-CROSS-003 and VAL-CROSS-007 (base leg).
The scheduler error-log test only restored the logger's .disabled flag, so a
bittensor import (forces existing loggers to CRITICAL) or alembic fileConfig
(logging.disable) run earlier in the process silenced the ERROR record and
failed the test only in the full alphabetical suite. Snapshot and neutralize
logging.disable, the scheduler logger's .disabled/.level/.propagate in a
fixture, capture on its own logger, then restore. Assertions unchanged (a
compute raise is logged and the schedule keeps ticking).
…-021)

With the flag OFF the master bridges an attested agent-challenge submission
exactly like legacy: cpu units at R=1, no worker plane / reconciliation, and
the legacy reassign-on-failure (never replicate) path (owner crash -> revert
-> reassign to a different validator, +1 attempt, zero worker replicas). The
sibling gpu R=2 replica in VAL-CROSS-003 keeps this non-vacuous. bittensor-free
(reuses the file's fixtures) to avoid the supervisor-weights log-test ordering
hazard.
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 72abdf2a-baf5-4488-a8d9-a5616ce268fd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mission/phala-attest

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant