Skip to main content

Action Circuit

The Action circuit is the heart of Platus. Every private transaction is a sequence of Actions, and each Action is one UltraHonk proof. All Actions share one verification key and emit one public field — the two properties that make the recursive aggregation tree uniform.

What one Action proves

A single Action spends up to two input notes and creates up to two output notes, under one owner key triple (ak, nk, rivk) and one net value commitment cv_net:

Per-input constraints

For each input, gated on enable_spend:

#ConstraintPurpose
1v_old·(1 − enable_spend) == 0 then v_old < 2^128dummy ⇒ zero value; real value in range
2recompute cm_old = action_note_commit(...)bind the witnessed note fields
3gd_old in subgroup; pkd_old == ivk·gd_old (gated)ownership — prover holds the ivk that owns the note
4nf == derive_nullifier(nk, ρ_old, ψ_old, cm_old)the published nullifier is correct (always enforced)
5commitment_root == binary_merkle_root(cm_old, pos, sibs) (gated)membership in a depth-16 tree
6rk = ak + α·Grerandomized spend-auth key returned to main

Per-output constraints

For each output, gated on enable_output, with rho_new = the paired input's nullifier:

#ConstraintPurpose
1v_new·(1 − enable_output) == 0 then v_new < 2^128dummy ⇒ zero value; real value in range
2gd_new, pkd_new in subgroup; ψ_new ≠ 0no fund lockup; no ECDH coset leak; preserve nullifier entropy
3cm_new == action_note_commit(..., rho_new, ...) (gated)output commitment is correct, with chained ρ
4esk ≠ 0, canonical; epk == esk·gd_new (always enforced)scanner can always recompute the shared secret

Spend-authorization (in main.nr)

action() returns (rk1, rk2); main then calls verify_spend_auth for each input, gated on enable_spend, against the bundle's auth_ctx:

e = low_251(Poseidon2(SPEND_AUTH_DOMAIN, R.x, R.y, rk.x, rk.y, auth_ctx))
verify s·G == R + e·rk # as one 2-point Straus MSM: s·G + e·(−rk) == R

auth_ctx is folded into the digest, so the on-chain publicsDigest check enforces that the proof verified the signatures against the same context the contract reconstructs. Full rationale: Spend Authorization.