# Architecture

## High-level flow

```
                 ┌──────────────┐
                 │   Depositor  │
                 └──────┬───────┘
                        │ note generated locally
                        │ commit = Poseidon(nullifier, secret)
                        ▼
            ┌────────────────────────┐
            │  Pool contract (Tolk)  │
            │  ─ pool_native.tolk    │
            │  ─ pool_jetton.tolk    │
            │                        │
            │  emits log_deposit      │
            └─────────┬──────────────┘
                      │ ext_out_msg
                      ▼
            ┌────────────────────────┐
            │  Indexer (Toncenter)   │
            └─────────┬──────────────┘
                      │ insert into postgres.deposits
                      ▼
            ┌────────────────────────┐
            │  TreeMirror            │
            └─────────┬──────────────┘
                      │ merkle proof
                      ▼
                 ┌──────────────┐
                 │   Withdrawer │
                 └──────┬───────┘
                        │ note (private)
                        │ + recipient
                        ▼
            ┌────────────────────────┐
            │  Relayer (REST)        │
            │  builds proof,         │
            │  submits to pool,      │
            │  pays gas, takes fee   │
            └─────────┬──────────────┘
                      │
                      ▼
            ┌────────────────────────┐
            │  Pool contract (Tolk)  │
            │                        │
            │  verify Groth16,       │
            │  mark nullifier spent, │
            │  send funds to         │
            │   recipient + relayer  │
            └────────────────────────┘
```

## Components

| Component     | Path                                      | Responsibility                          |
| ------------- | ----------------------------------------- | --------------------------------------- |
| Tolk pool     | `apps/contracts/contracts/pool_*.tolk`    | On-chain anonymity pool                 |
| Tolk verifier | `apps/contracts/contracts/verifier.tolk`  | Groth16 verify (auto-gen)               |
| Circuit       | `apps/contracts/circuits/withdraw.circom` | The Groth16 statement                   |
| SDK           | `packages/core/`                          | Note + proof + tree + client primitives |
| CLI           | `apps/cli/`                               | User-facing commands                    |
| Relayer       | `apps/relayer/`                           | REST service that submits withdraws     |

## Data flow

1. **Note generation.** Off-chain only. Sample 31-byte `nullifier` and 31-byte `secret`. Compute `commitment = Poseidon(nullifier, secret)` and `nullifierHash = Poseidon(nullifier)`. Serialise as `tonado-<asset>-<amount>-<network>-<hex>`.
2. **Deposit.** User wallet sends an internal message with op `DEPOSIT_NATIVE` (or jetton `transfer` with `forward_payload` containing the commitment). The pool inserts the commitment into its Merkle tree and emits a `log_deposit` ext-out-msg with `(commitment, leafIndex, timestamp)`.
3. **Indexing.** The relayer's `indexerWorker` polls Toncenter, decodes log out-messages, and persists them to Postgres. The `TreeMirror` rebuilds the `fixed-merkle-tree` on demand.
4. **Withdraw.** User sends `(note, recipient)` to the relayer. Relayer constructs a Merkle inclusion proof, runs snarkjs Groth16 over the BLS12-381 zkey, packages everything into a `WITHDRAW` message, signs from its own wallet, and broadcasts. On-chain the pool:
   * checks `is_known_root(root)`
   * checks `!nullifier_spent(nullifierHash)`
   * calls `verifier_verify(proof, publicSignals)`
   * marks nullifier spent
   * sends `denomination - fee` to recipient, `fee` to relayer
   * emits `log_withdraw`

## Cryptographic primitives

|                                | Choice                                                |
| ------------------------------ | ----------------------------------------------------- |
| Curve                          | BLS12-381 (TVM v4 native pairing)                     |
| Hash inside circuit & tree     | Poseidon (`circomlib`)                                |
| Proving system                 | Groth16                                               |
| Note nullifier/secret size     | 31 bytes each (248 bits, fits below BLS scalar field) |
| Merkle tree height             | 20 (1,048,576 leaves)                                 |
| Root history retained on-chain | 30                                                    |
| ZERO\_VALUE                    | `keccak256("tornado") mod r_BLS12_381`                |

## Why these choices

* **BLS12-381**: TON's TVM has native opcodes for BLS12-381 pairing and group ops. BN254 (Tornado's curve) has no native support; we'd be implementing pairing in software, which doesn't fit gas limits.
* **Poseidon over MiMC**: MiMC's round constants in `circomlib` were derived for BN254. Poseidon's spec accommodates arbitrary prime fields and is what the TON ZK ecosystem standardises on.
* **Groth16 over PLONK/Halo2**: snarkjs's Groth16-BLS12-381 path is the best-supported in TON's `export-ton-verifier` tool; the verifier is small and fast on-chain.

## Address ↔ field-element mapping

The circuit binds `recipient` and `relayer` as 256-bit field elements. The mapping is a raw interpretation of the 256-bit address hash (workchain bits are folded into the field). Implementation: `addressToFieldElement` in `packages/core/src/tonClient.ts`. The on-chain pool reverses this when emitting log\_withdraw and when constructing the public-signals cell for verification.

For workchain = 0 (the common case), this is just the address hash as a 256-bit integer.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tonadocash.com/protocol-reference/architecture.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
