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

# STARK Compliance Proofs

> Prove a private amount satisfies a policy without revealing it — zero-knowledge proofs for VES events.

`stateset-stark` generates witness-level cryptographic proofs that **a private amount satisfies a
compliance policy, without revealing the amount**.

It's built on [Winterfell](https://github.com/facebook/winterfell), using STARKs — transparent
(no trusted setup) and post-quantum secure.

## Why this exists

Compliance rules usually need the value they're checking. If an order amount is encrypted, an
auditor asking "did every order stay under the AML threshold?" normally has to be given the
amounts.

A STARK proof answers the question instead of disclosing the data: the prover demonstrates the
constraint held, the verifier checks the proof, and nobody sees the amount.

## Supported policies

| Policy                   | Proves                                                   |
| ------------------------ | -------------------------------------------------------- |
| `aml.threshold`          | amount **\<** threshold (strict)                         |
| `order_total.cap`        | amount **≤** cap (non-strict)                            |
| `agent.authorization.v1` | amount ≤ `maxTotal` for a delegated commerce intent hash |

<Note>
  `aml.threshold` is strict and `order_total.cap` is not. A value exactly equal to the bound passes
  the cap and fails the threshold — pick deliberately.
</Note>

## Characteristics

| Property        | Value                                                   |
| --------------- | ------------------------------------------------------- |
| Field           | Goldilocks (p = 2^64 − 2^32 + 1)                        |
| Hash            | Rescue-Prime (7 rounds, α = 7)                          |
| AIR constraints | 157                                                     |
| Security        | 82-bit `fast` profile, 100+-bit `secure` — configurable |
| Prove time      | tens of ms                                              |
| Proof size      | tens of KB                                              |
| Verify time     | single-digit ms                                         |

<Warning>
  The default `fast` profile is **82-bit** security, below the 128-bit level often assumed by
  default. Use the `secure` profile for anything where a proof is externally relied upon. Figures
  above are order-of-magnitude guidance — reproduce with `cargo bench --bench stark_bench`.
</Warning>

## Generate a proof

```rust theme={null}
use ves_stark_prover::{ComplianceProver, ComplianceWitness, Policy};

// The witness holds the private amount plus the public inputs
let witness = ComplianceWitness::new(amount, public_inputs);

let policy = Policy::aml_threshold(10_000);
let prover = ComplianceProver::with_policy(policy);

let proof = prover.prove(&witness)?;
println!("proof size: {} bytes", proof.proof_bytes.len());
```

## Verify a proof

```rust theme={null}
use ves_stark_verifier::verify_compliance_proof_auto_bound_strict;

let result = verify_compliance_proof_auto_bound_strict(
    &proof.proof_bytes,
    &public_inputs,
)?;
assert!(result.valid);
```

Verification needs only the proof bytes and the public inputs — no access to the prover, and no
access to the amount.

## Submit to the sequencer

```rust theme={null}
use ves_stark_client::{ProofSubmission, SequencerClient};

let client = SequencerClient::try_new("http://localhost:8080", "api_key_here")?;

// Fetch canonical public inputs for the event and validate them
let inputs = client
    .get_public_inputs_validated(event_id, "aml.threshold", 10_000)
    .await?;

let witness = ComplianceWitness::new(amount, inputs);
let proof = ComplianceProver::with_policy(Policy::aml_threshold(10_000)).prove(&witness)?;

let submission = ProofSubmission::aml_threshold(
    event_id,
    10_000,
    proof.proof_bytes,
    proof.witness_commitment,
);
client.submit_proof(submission).await?;
```

<Tip>
  Use `get_public_inputs_validated` rather than assembling inputs yourself. It returns the canonical
  form the sequencer will verify against — inputs that differ even in ordering produce a proof that
  fails verification.
</Tip>

## Crates

| Crate                  | Purpose                                      |
| ---------------------- | -------------------------------------------- |
| `ves-stark-primitives` | Field arithmetic, Rescue hash, public inputs |
| `ves-stark-air`        | AIR constraint definitions                   |
| `ves-stark-prover`     | Proof generation                             |
| `ves-stark-verifier`   | Proof verification                           |
| `ves-stark-batch`      | Batch proofs for aggregate state transitions |
| `ves-stark-client`     | Sequencer and Set Chain HTTP client          |
| `ves-stark-cli`        | CLI — binary `ves-stark`                     |

**Bindings:** WebAssembly, Node.js (`@stateset/ves-stark`), Python (`ves_stark`), and C FFI via
Zig.

```toml theme={null}
[dependencies]
ves-stark-prover = "0.3"
ves-stark-verifier = "0.3"
ves-stark-primitives = "0.3"
```

Published on crates.io.

## Where proofs end up

A generated proof is submitted to the [sequencer](/stateset-sequencer/stateset-sequencer), which
anchors its hash and the policy hash on
[Set L2](/set/stateset-set-l2-architecture#compliance-proofs) alongside the batch commitment. A
third party then verifies it independently — see
[Compliance proofs](/set/stateset-set-l2-compliance-proof).

## Related

* [Set L2 Compliance Proofs](/set/stateset-set-l2-compliance-proof) — verifying an anchored proof
* [Set L2 Architecture](/set/stateset-set-l2-architecture)
* [Sequencer Architecture](/stateset-sequencer-architecture)
