OpaqueReputationVerifier.
Prerequisites
- WASM module (
wasmModuleSpecifier) - Native announcement rows with V2 PSR attestation metadata
snarkjs(pulled in by@opaquecash/psr-prover)- Circuit artifacts (default: hosted on opaque.cash
/circuits/...)
Step 1: Discover traits
discoverTraitsV2 validates each 0xB2 marker against the chain’s schema registry and
returns only traits issued by an authorized schema authority or delegate. Fetch rows from
the native chain, not UAB, because relayed payloads cannot carry the full V2 metadata.
Step 2: Reconstruct the stealth signing key
Step 3: Build the action scope
OpaqueClient.buildReputationActionScope / reputationExternalNullifierFromScope).
Step 4: Generate the proof
trait comes from discoverTraitsV2, the SDK uses the trait’s V2 Merkle leaf
preimage fields automatically. You only need to pass issuerPkX, traitDataHash, or
nonce yourself for custom witness construction.
Step 5: Fetch a valid Merkle root
Step 6: Simulate (optional)
Step 7: Verify view (read-only)
Step 8: Submit on-chain
Consumes the nullifier on success:The same Groth16 proof — from the same trusted setup — verifies on Ethereum, Solana, and
Starknet. On Starknet (Sepolia, testnet preview) PSR is verification and gating only: the
OpaqueReputationVerifierV2 Groth16 verifier plus the PsrGate credential-gated-entry contract,
via @opaquecash/psr-chain-starknet (getStarknetDeployment("sepolia")). Schema registration and
attestation issuance stay on Ethereum and Solana. See Starknet for the full
flow and caveats.Full flow diagram
Each
(trait, externalNullifier) pair can only be verified once. Choose scopes carefully per action you gate.