Notraildevnet

Notrail docs

Overview

Notrail is a shielded pool on Solana. Instead of account balances, value lives in notes, which are Poseidon commitments to(amount, owner, blinding), stored as leaves of an on-chain Merkle tree. Spending a note means proving in zero knowledge that you know a note in the tree, that you own it, and that the outputs balance. The only thing revealed is a one-time nullifier, so the note can't be spent twice.

There are two pools today, each with its own tree and vault: native SOL and the sUSDC test token.

Quickstart

  1. Switch Phantom, Solflare or Backpack to Devnet, and get test SOL from faucet.solana.com.
  2. Open the app, connect, and sign the unlock message. That derives your keys locally.
  3. Shield an amount. Want tokens? Use the in-app faucet for 1,000 sUSDC.
  4. Copy your notrail1… address from Receive and share it, or send privately to someone else's.
  5. Unshield to a fresh wallet. Read the privacy check first.

Privacy model

HiddenBalances, sender and recipient of private transfers, amounts of private transfers, links between deposits and withdrawals, your history.
PublicThat a deposit or withdrawal happened, its amount, and the public wallet involved. That some private transfer happened, and the relayer that submitted it.

Your anonymity set is everyone who has deposited into the same pool. Timing and amounts are the most common ways people leak. The privacy check in the Unshield tab warns about withdrawing soon after a deposit, matching amounts, precise amounts and reused wallets.

Protocol

Circuit

A Circom 2 join-split with 2 inputs and 2 outputs, 26,784 constraints. Public inputs:

root, publicAmount, extDataHash, inputNullifier[2], outputCommitment[2]

commitment = Poseidon(amount, ownerPubkey, blinding)
ownerPubkey = Poseidon(spendKey)
nullifier   = Poseidon(commitment, leafIndex, Poseidon(spendKey, commitment, leafIndex))
Σ inAmount + publicAmount = Σ outAmount       (amounts range-checked to 64 bits)
publicAmount = extAmount − fee  (mod p)

Zero-value inputs skip the Merkle check, so new users can deposit with dummy inputs.

On-chain program

Trusted setup

Phase 1 uses the PSE Perpetual Powers of Tau (80 contributions). Phase 2 is currently a single Notrail contribution, which is fine for a testnet. A public multi-party ceremony is required before mainnet.

Keys & addresses

Signing the unlock message gives a 64-byte ed25519 signature, which is deterministic for a given wallet. It's hashed into a spending key (a BN254 scalar) and an x25519 viewing key. Your address notrail1… encodes Poseidon(spendKey) ‖ x25519 public key. Senders encrypt each note to the viewing key with an ephemeral x25519 key (87 bytes on-chain). Keys live in tab memory only.

Relayer

Private sends and withdrawals go to /api/relay, which checks the request, signs as fee payer and submits it. The relayer earns a flat fee from the shielded amount (0.005 SOL or 0.5 sUSDC), which covers rent for the nullifier and note accounts. It can't steal funds or change the recipient, because everything is bound by the proof. At worst it can refuse to relay.

Security

Compliance

Notrail is built for selective disclosure. Share your viewing key to show incoming payments on the audit page, or export a signed CSV report of your activity from Keys & compliance. Your wallet signs a SHA-256 digest of the report, so anyone can check it wasn't edited.