// additively homomorphic balances

Count it.
Never show it.

Status: Ticker (placeholder, no token exists):
// 01 · the homomorphic sum check

Add sealed numbers. Open only the total.

Pick three amounts. Each is encrypted to one key. A “tallier” who never sees the key adds the ciphertexts point by point. The key holder decrypts the result — and gets exactly the sum.

A Encrypt → add ciphertexts → decrypt the sum

Amounts are whole units from 0 to 5,000,000 (the decrypted total must stay below 224 = 16,777,216 — see “why small numbers”).

// 02 · the working ledger

A public ledger of sealed amounts.

Open accounts, deposit, and send encrypted transfers. The ledger is what an observer sees: who transacted, and ciphertexts — never the amounts. Each transfer carries a zero-knowledge equality proof that anyone can check without a key.

B Accounts

Each account gets an ElGamal keypair generated in this tab. This page plays every account owner at once so you can try it alone — in a real system each secret key would sit only in its owner's wallet.

Keys exist only in this tab's memory and vanish on reload. Never paste a real wallet's seed phrase or private key anywhere on this page — it never asks for one.

C Send an encrypted transfer

The sender decrypts their own balance locally to check funds, then encrypts the amount twice — once to their own key (to subtract) and once to the recipient's key (to add) — and attaches a proof that both ciphertexts hide the same number.

D Public ledger observer view

Everything below is “on-chain” in this model. Deposits are public (money entering a confidential balance is visible, as in Token-2022). Transfer amounts appear only as ciphertext.

The ledger is empty.
// 03 · read a real mint

Does this token have confidential transfers switched on?

Paste a Solana mint address. The page asks mainnet (read-only, through this site's proxy) for the mint account with getAccountInfo + jsonParsed and lists its Token-2022 extensions.

E Token-2022 extension inspector

Examples:

An enabled confidentialTransferMint extension means the mint was configured for confidential transfers. It does not tell you whether any holder uses them, or whether the network's proof-verification program is currently available — check current Solana status before relying on it.

// how it works

Exponential ElGamal, in five lines

  1. Keys. A secret scalar sk; the public key is a curve point PK = sk·G on edwards25519.
    PK = sk · G
  2. Encrypt an amount m with fresh randomness r. The amount lives in the exponent, as m·G. Because r is new every time, the same amount never encrypts the same way twice.
    C₁ = r·G    C₂ = m·G + r·PK
  3. Add without opening. Adding two ciphertexts point-wise gives a valid encryption of the sum. Subtraction works the same way — that is how a sender's balance goes down.
    (C₁+C₁′, C₂+C₂′) = Enc(m+m′; r+r′)
  4. Decrypt. The owner strips the mask and is left with m·G. Recovering m from it is a discrete log — only feasible because m is small. This page uses baby-step giant-step over [0, 2²⁴).
    C₂ − sk·C₁ = m·G  →  m = BSGS(m·G)
  5. Prove, don't show. A transfer posts the amount encrypted to the sender and to the recipient, plus a Sigma-protocol proof (Fiat–Shamir, SHA-512) that both ciphertexts hide the same m. Any observer can verify it with public keys only.
    verify: s₁G = A₁ + cC₁ᴬ,  smG + s₁PKᴬ = A₂ + cC₂ᴬ, … (same for B)
PieceThis model (Ciphertally)Token-2022 confidential transfers
EncryptionExponential ElGamal on the edwards25519 prime-order subgroupTwisted ElGamal over Ristretto255: one Pedersen commitment plus a decrypt handle per key
ProofsCiphertext-equality proof onlyEquality, ciphertext-validity and range proofs, checked on chain by the ZK ElGamal Proof program
OverspendPrevented only by the sender's own page (no range proof)Range proof shows the new balance is non-negative
BalancesOne encrypted balance per accountPending + available balances, plus an AES-encrypted “decryptable balance” for fast owner reads
Amount sizeTotals below 2²⁴, decrypted directlyAmounts split into low/high bit chunks so each part stays small enough to decrypt
AuditorNoneOptional auditor ElGamal key set on the mint
// privacy model

What stays sealed, and what doesn't

Hidden (needs the account's secret key)

  • Each transfer amount
  • Each account's running balance
  • Whether two transfers were for the same amount (ciphertexts are randomized)

Public (anyone can see)

  • Which accounts sent to which — sender and recipient are not hidden
  • When transfers happen and how many there are
  • Deposit amounts (money entering a confidential balance) and, in Token-2022, withdrawals
  • Each account's ElGamal public key and every ciphertext

This is amount confidentiality, not anonymity. It reduces how much an observer learns; it does not hide who you are or who you pay.

Known limitations — please read

  • A model, not Token-2022. It shows the mathematical idea. It is not the Token-2022 program, does not produce Token-2022 instructions or proofs, and is not compatible with real confidential-transfer accounts.
  • No range proofs. Nothing on this ledger stops a dishonest sender from encrypting a negative or oversized amount; only the sender's own page checks funds. Real systems need range proofs for exactly this reason.
  • Small numbers only. Decryption is a bounded discrete-log search. Totals at or above 2²⁴ (or below zero) cannot be read back.
  • Not constant-time. The curve arithmetic is hand-written BigInt code for teaching. It leaks timing and has had no security review. Do not reuse it for anything of value.
  • Metadata is public. Who pays whom, when, and how often stays visible. Amount privacy does not provide anonymity.
  • One page plays everyone. All demo keys sit in one tab so you can try both sides. They are never stored or sent anywhere, and disappear when you reload.
  • Mint check is a read. It reports what the mint account says. Whether confidential transfers are usable right now depends on the network, wallets and proof program status, which this page does not check.