Documentation
Proof-Carrying Authorization (PCA) is a cryptographic authorization model that replaces identity-centric access control with proof-based authorization.
Introduction
Instead of asking whether a principal is allowed to perform an action, a verifier checks a non-interactive zero-knowledge (NIZK) proof. This proof attests that some witness exists satisfying a policy predicate bound to the action, context, and public inputs.
This model provides:
- Privacy: Hides the authorizer identity.
- Composability: Policies can be reused across programs.
- Replay Resistance: Nullifiers prevent double-authorization.
The Model
Statement Encoding
The fundamental statement proven in PCA is constructed by encoding the action, context, and public inputs:
stmt = enc(action) || enc(context) || enc(public_inputs)Scope Binding
To prevent cross-protocol attacks, the proof is bound to a specific scope:
scope = SHA256(DST_SCOPE || action || context || SHA256(p_pieces))Nullifiers
To ensure an authorization can only be used once, a nullifier is derived from the secret witness and the scope:
nf = SHA256(DST_NF || domain || spend_key || scope)The verifier tracks used nullifiers to reject replays.
Implementation
The current implementation targets Solana using the Pinocchio library for on-chain verification and Groth16 proofs.
Public Input Layout
The verifier expects public inputs in a specific order (big-endian 128-bit limbs padded to 32 bytes):
0: scope_hi 1: scope_lo 2: domain_hi 3: domain_lo 4: nf_hi 5: nf_loExamples
- Private Payments: SPL vault withdrawals authorized by a PCA proof (
programs/private_payments). - Private Allowlist: proof-gated access to a resource with a dedicated circuit (
circuits/allowlist_gate.circom,programs/private_allowlist).
Get Started
Explore the codebase to see the circuit definitions and Solana program implementation.