daitchain

x/tee_attest Real (skeleton)

On-chain verification of hardware TEE attestation quotes. Three vendor paths: Intel TDX, AMD SEV-SNP, and NVIDIA NRAS-JWT. Quote bodies stay off-chain; only the verification result and content hash live on-chain.

Three verification paths

VendorLibrary (Phase 1)RootsTCB enforcement
Intel TDXgithub.com/google/go-tdx-guest v0.3.1embedded SGX provisioning rootsper-FMSPC governance minimum
AMD SEV-SNPgithub.com/google/go-sev-guest v0.14.1embedded ARK + ASKper-chip-family minimum (VLEK supported)
NVIDIA NRASgithub.com/golang-jwt/jwt/v5 + pinned NVIDIA JWKSNRAS JWKS pinned in TrustRootsper-architecture minimum

NVIDIA gets a Phase-2 follow-up: full local NRAS verifier port (4-6 weeks of engineering) drops the JWKS-pinning dependency entirely.

Determinism rules

The MsgVerifyAttestation wire format

FieldTypeNotes
host_addrbech32operator address (signer)
tee_kindenumNVIDIA_NRAS / INTEL_TDX / AMD_SEV_SNP
evidence_hash32 Bsha256 of full quote
nonce32 Bchain-issued epoch nonce (must match)
bound_pubkey32-256 Bsession key bound in REPORTDATA
quote_blob5-20 KBNOT permanently stored on-chain
cert_chain0-16 KBvendor cert chain (Intel/AMD); empty for NRAS
quote_heightint64block height included in nonce derivation
da_uristringoff-chain DA pointer (ipfs://, ar://, ...)

REPORTDATA binding

REPORTDATA = sha256( chain_id || host_addr || epoch_nonce || session_pubkey )

Each vendor's quote body has its own REPORTDATA / userdata field; the per-vendor verifier extracts it and compares to this digest. Quotes that do not bind session_pubkey this way are rejected.

Attestation ID

attestation_id = hex(sha256(quote_blob))

Epoch nonce derivation

nonce_next = sha256( ctx.BlockHeight() (BE 8B) || ctx.HeaderHash() )

Rotated every Params.EpochNonceRotationBlocks blocks (~10 minutes default). Fully deterministic across all validators.

Storage strategy

Quote bodies are stored OFF-CHAIN (Celestia, IPFS, Arweave). The keeper persists ~250 B per record:

attestation_id              sha256(quote) hex
tee_kind                    vendor enum
mrtd_or_measurement_digest  TDX MRTD / SNP MEASUREMENT / NRAS measurement
bound_pubkey                session key
valid_until                 block height
host_addr                   bech32
accepted_at_height          block height
da_uri                      off-chain DA pointer
status                      ACCEPTED / CHALLENGED / REVOKED

TCB update flow

  1. Vendor publishes a TCB recovery (Intel) / firmware bump (AMD) / JWKS change (NVIDIA).
  2. Off-chain security working group verifies the publication's signature and posts a gov proposal carrying MsgRegisterTrustRoot and / or MsgUpdateTcbInfo.
  3. Validators vote. On pass, x/gov calls the keeper handlers.
  4. From the next block onward, every MsgVerifyAttestation checks the new minimum / root set. Older records remain ACCEPTED until valid_until expires.

Other messages

MsgRegisterTrustRoot      // gov-only; add or revoke a TCB root
MsgUpdateTcbInfo          // gov-only; update per-(tee_kind, platform_id) minimum
MsgEvidenceChallenge      // anyone; challenges a stored result, posts bond

Queries

ABCI++ vote extensions

x/pouw consumes attestation results via vote extensions. The wire format:

VoteExtension = proto.Marshal(VoteExt{
    Receipts: []ReceiptCommitWithAttestation{
        {commit_hash, host_addr, attestation_id}
    }
})

What's wired today

Real Module wiring, params, KV layout (with host index + expiry index), trust-root and TCB-info registry CRUD (gov-only), all read queries, MsgVerifyAttestation dispatch, MsgEvidenceChallenge bond escrow, deterministic epoch-nonce rotation, IsAttestationValid (the surface x/pouw consumes).

Phase 1 Per-vendor verifier bodies (TDX, SEV-SNP, NRAS), REPORTDATA extraction from parsed quotes, EndBlock pruning of expired records, challenge re-verification with bond settlement, ABCI++ ExtendVote / VerifyVoteExtension bodies.

See also