> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pinaivu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# On-Chain Contracts (Sui Move)

> pinaivu::enclave, pinaivu::receipts, pinaivu::vault

Source: `Pinaivu-AI/contracts`. Three modules, each building on the one
before it:

```
pinaivu::enclave   ← root of trust: register PCRs + attested pubkey
       │
       │ verify_signature<ENCLAVE, P>()
       ▼
pinaivu::receipts  ← typed payload shape that matches Rust's BCS encoding
       │
       │ verify_completion_receipt(...)
       ▼
pinaivu::vault     ← treasury + settle(payee, amount, signature)
```

## `pinaivu::enclave`

* **`EnclaveConfig<ENCLAVE>`** — shared object holding the expected PCR
  triple. The admin holding `Cap<ENCLAVE>` rotates PCRs after every
  reproducible build via `update_pcrs`.
* **`Enclave<ENCLAVE>`** — shared object created by `register_enclave`
  after a fresh NSM attestation document is verified against the config's
  PCRs. Stores the Ed25519 pubkey extracted from that document.
* **`verify_signature<ENCLAVE, P: drop>(enclave, intent, timestamp_ms,
  payload, signature)`** — wraps the payload in an `IntentMessage`,
  BCS-encodes it, and verifies with Sui's `ed25519` precompile.

## `pinaivu::receipts`

* `Payout { sui_address: address, amount: u64 }`
* `ReceiptPayload { request_id: vector<u8>, aggregated_output_hash:
  vector<u8>, payouts: vector<Payout> }`
* `verify_completion_receipt(enclave, timestamp_ms, request_id, hash,
  payouts, &signature)` — convenience wrapper that calls
  `enclave::verify_signature::<ENCLAVE, ReceiptPayload>(...)` with the
  reserved `INTENT_ROUTING_RECEIPT = 1` intent scope.

## `pinaivu::vault`

A **treasury model** — Pinaivu pre-funds a shared `Balance<T>` per
supported coin type. Clients do **not** deposit per request (see the
[honest centralization caveat](/architecture/decentralization#where-centralization-still-genuinely-exists)
about this being an intentional simplification, not the long-term design).

```move theme={null}
Vault<phantom T> {
    treasury: Balance<T>,
    settled:  Table<(request_id || payee), bool>,  // dedupe
}

public fun new_vault<T>(ctx)
public fun top_up<T>(vault, payment)          // Pinaivu funds the pool
public fun settle<T>(
    vault, enclave,
    request_id, payee, amount,
    timestamp_ms, aggregated_output_hash, payouts,
    signature,
    ctx,
)
public fun treasury_balance<T>(vault): u64
```

`settle` aborts unless:

1. `(request_id, payee)` hasn't been settled before
2. `verify_completion_receipt(...)` returns true (signature valid)
3. `(payee, amount)` appears in the `payouts` list
4. The treasury has enough balance left

Emits `TreasuryToppedUp` + `Settled` events for the off-chain explorer to
index.

### Why `settle` is safe even if the coordinator operator key leaks

The **operator key** (held by the in-enclave sidecar) signs and submits
the `settle()` PTB but does **not** authorise the disbursement. The
disbursement is authorised by the separate **enclave-attested Ed25519
key** (registered via `register_enclave`) which signs the
`ReceiptPayload` BCS bytes. The sidecar cannot forge that signature — only
the coordinator running attested code can.

A compromised operator key can pay gas to submit valid receipts faster, or
DOS the vault by submitting bogus PTBs (they all abort without moving
money). It cannot drain funds. This split is the practical expression of
the Sui pillar described in [Decentralization & verifiability model](/architecture/decentralization#2-sui-making-the-coordinators-attestation-and-payouts-publicly-checkable).

## Deploy outline

```bash theme={null}
# 1. Publish
cd contracts && sui client publish --gas-budget 200000000
# → PackageId, Cap<ENCLAVE>, EnclaveConfig<ENCLAVE> object ids

# 2. Set real PCRs (reproducible build emits coordinator.pcrs)
sui client call --package $PKG --module enclave --function update_pcrs \
  --type-args "$PKG::enclave::ENCLAVE" \
  --args $CONFIG $CAP <pcr0_hex> <pcr1_hex> <pcr2_hex>

# 3. One vault per coin type (SUI shown)
sui client call --package $PKG --module vault --function new_vault \
  --type-args "0x2::sui::SUI"

# 4. Top up
sui client call --package $PKG --module vault --function top_up \
  --type-args "0x2::sui::SUI" --args $VAULT_ID $FUNDING_COIN_ID
```

## Coordinator registration

Registration is **authoritative on the EC2 host**, not inside the enclave.
The in-enclave path still runs in parallel (capped retries) for
redundancy, but its calls go through the sidecar's HTTPS bridge to Sui RPC
and tend to lose a race against `update_pcrs`: when an enclave's NSM
attestation contains PCRs that differ from `EnclaveConfig.pcrs` on-chain,
`register_enclave` aborts with `EInvalidPcrs`. The host-side path runs
`update_pcrs` first and therefore always converges.

The host's `scripts/register-coordinator.sh`:

1. Parses `out/coordinator.pcrs`.
2. Calls `enclave::update_pcrs` so the on-chain `EnclaveConfig<ENCLAVE>`
   matches this build's PCRs.
3. Fetches the live enclave's NSM document from `GET /get_attestation`.
4. Converts the attestation bytes into a Sui CLI PTB vector literal.
5. Chains `0x2::nitro_attestation::load_nitro_attestation` →
   `pinaivu::enclave::register_enclave<ENCLAVE>(config, cap, doc)` in a
   single transaction.
6. Extracts the new `Enclave<ENCLAVE>` shared object id from the
   transaction's object changes.
7. Persists `PINAIVU_ENCLAVE_OBJECT_ID` so the next enclave boot picks it
   up automatically.
8. Pushes the new id into the **currently running** coordinator via an
   authenticated admin endpoint, so `vault::settle` calls work in the
   same deploy that registered.

<CardGroup cols={2}>
  <Card title="Why Sui" icon="circle-question" href="/architecture/why-sui">
    Why this is built on Move + Nautilus + Walrus specifically, not "a chain"
  </Card>

  <Card title="Glossary" icon="book" href="/reference/glossary">
    PCR, NSM, EIF, IntentMessage, and every other term used on this page
  </Card>
</CardGroup>
