Spend Authorization
Value conservation (the binding signature) is not enough: a malicious party who saw a note's public data could still try to spend it. Spend authorization proves the note's owner approved this specific spend. In Platus this is a BabyJubJub Schnorr signature, rerandomized per input and verified inside the Action circuit.
Rerandomization: hiding the key
Publishing the owner's verifying key ak on every spend would link all of a user's spends. Platus rerandomizes it per input:
with a fresh random α per input. rk = rsk·G, so a signature under rsk verifies against rk — but rk is unlinkable to ak because α is fresh. The circuit derives rk from the private (ak, α) (it is not a free public input), and rejects α = 0 (which would republish ak verbatim).
The signature, verified in-circuit
The Schnorr equation is s·G = R + e·rk, with a Poseidon2 challenge:
The SDK signs , rejection-sampling the nonce until e ∈ [1, r) (the 251-bit reduction can exceed r ≈ 2^{250.6} ~25% of the time). The circuit (verify_spend_auth):
- recomputes
eidentically, assertseandsare canonical BJJ scalars, - subgroup-checks
rkandR, - checks
s·G = R + e·rkas a single 2-point Straus MSM (s·G + e·(−rk) = R), and - gates the equality on
enable_spend— a dummy input carries an in-range dummy signature that is not enforced, mirroring the on-chainenableSpendsgate.