On-chain overview

Protocol15's on-chain surface is four Anchor programs on devnet. Mainnet is not enabled. This section documents each one as it is deployed: its purpose, PDAs, accounts, instructions, and how to call it. The SDK builds these instructions for you (see @p15/blind-mode); this section is the ground truth underneath.

The programs

ProgramIdRole
note-vault7gtXhpwEaYHKJ9XpAX7Z4BNjXU3cFCq4CNyzMQpFaQZ2The shielded pool. Holds deposits, verifies private transfers, releases withdrawals.
transfer verifier14C9wbz3Eg6nx6A4GNNE2DqkgdZGKnxhp4TLMJkD7Pw3Groth16 verifier for the 1-in/2-out transfer circuit. Called by note-vault via CPI.
psol-wrapper5LQUmd355dcXkETDheBXavpaBzJq4JFWLb9mfkku31ZRLegacy 1:1 SOL to pSOL wrapper. Not on the active path (the dApp uses native wSOL).
stealth-vault7oFAWawZCxDivMSa73hGh5V4XnhukLbrZQTA9Sq2r2pkNon-revocable custody for one-time Token-2022 CT accounts. Tied to the disabled CT path.
policy3B8sqPfgKYvxffwCvPx76Syu4R6MzQr7wkiTmvfjEzLROptional on-chain allowlist and per-transaction limit. Not wired into the dApp.

A note on the token program

Protocol15 does not use Token-2022 Confidential Transfers or ZK ElGamal. That path is disabled. Privacy comes entirely from the Noir/Groth16 note model in note-vault, on top of plain SPL transfer_checked. The active token program is the legacy SPL Token program: SOL is handled as native wrapped SOL (So111…112), and USDC is legacy SPL too. note-vault uses Anchor's TokenInterface, so it can hold a Token-2022 mint as well, but nothing on the active path requires Token-2022. The two programs that do use Token-2022 (psol-wrapper and stealth-vault) belong to the disabled CT design.

How they fit together

The active amount-privacy engine is note-vault: a shielded pool where every balance is a hidden note. A blind transfer is one spend on note-vault, gated by a Groth16 proof the transfer verifier checks. SOL enters and leaves the pool as native wrapped SOL on the legacy Token program (wrap = create the wSOL ATA, transfer lamports, SyncNative; unwrap = CloseAccount).

code
make private:   SOL --wrap (native wSOL, legacy Token)--> wSOL --note-vault.deposit--> private note
blind send:     private note --note-vault.spend (proof)--> recipient note + change
withdraw:       private note --note-vault.withdraw--> wSOL --unwrap (CloseAccount)--> SOL

psol-wrapper is a separate, program-minted SOL wrapper (pSOL, a Token-2022 CT mint) from the earlier CT design. The current note-model dApp wraps SOL natively instead, so psol-wrapper is documented but not on the active flow.

stealth-vault is the alternative custody design for the Token-2022 Confidential Transfer path. That path is disabled in favour of the note model, so the program is deployed but not on the active flow. It is documented because the recipient-only ownership gate it pioneered (R = spend_pub + t*G as a required signer) is the same gate note-vault uses.

policy is an optional escalation a deployer can prepend or CPI into the make-private boundary. The active screening path is the off-chain screening provider; policy is for unskippable on-chain enforcement.

Conventions used across these pages

  • PDAs are derived with Pubkey.findProgramAddress(seeds, programId). Each program page lists its seeds.
  • Amounts are u64 base units. pSOL and wrapped SOL use 9 decimals, so base units equal lamports.
  • Recipient-only ownership. note-vault and stealth-vault both require the recipient-only key R as a transaction signer. The sender can compute R but cannot sign as it, which is what makes payments final.
  • Field encoding. Commitments and owners are BN254 field elements, big-endian, to match the gnark public witness. The SDK's noteCommitment, assetField, and pubkeyToField mirror the program's Poseidon encoding exactly.

Trust assumptions

  • The programs' upgrade authorities (flagged for a multisig and burn before any real mainnet use).
  • The per-circuit Groth16 trusted setup behind the transfer verifier.
  • Everything else is structural: there is no admin or operator key that can move pooled funds. Tokens leave note-vault only through withdraw, gated on a recipient signature, a recomputed commitment, and a live note marker.