Psy Architecture

Treatise No. 001 — Edition 2026

An architecture
of math, not
of trust.

Psy is a zero-knowledge–native independent chain for private, internet-scale payments. Every balance, every transfer, every bridge receipt is settled by a recursive Plonky2 proof — the chain verifies the math, not your financial life. This treatise walks the architecture end to end: from a single user pressing send, through the Goldilocks field, the realm processors, the coordinator's rollup-state-transition proof, and out the other side as a single calldata blob on Ethereum that anyone can verify in sub-millisecond gas.

Psy 是一条以零知识证明为原生范式的独立公链,专为私密、互联网级别的支付而生。 余额、转账、跨链回执——皆由递归式 Plonky2 证明结算;链上验证的是数学,不是你的财务生活。 本论以工程视角自始至终拆解 Psy 的体系:从一名用户点下 send 的瞬间, 穿过 Goldilocks 有限域、穿过 realm 处理器、穿过协调器的"汇总状态迁移证明", 最终以一段 calldata 落到以太坊,让任何人都能在亚毫秒级 gas 下完成验证。

No. 1

Manifesto — Why a new chain

/ 宣言 — 为何需要一条新链

The dominant payment networks of the last fifty years built their trust the same way: publish everything. Every cleared check, every interbank transfer, every stablecoin transaction sits in a ledger that anyone with credentials can read and that everyone with subpoena power eventually does. We treated this as the cost of having a working economy. It was not. It was the cost of not having a good enough cryptosystem.

Psy is what becomes possible when that cryptosystem finally arrives. Recursive zero-knowledge proofs over the Goldilocks field let us deliver a payment receipt that is simultaneously universally verifiable and completely private: an outsider can be sure your transfer was well-formed, that you had the balance, that the receiving user is registered, that the system invariants still hold — without learning who you are, who you paid, or how much.

The chain that runs underneath this promise has to be more than “Ethereum but private.” A private rollup that still pays for every block on a public host inherits the host's economics, latency, and censorship surface. Psy is an independent chain: its own validator set, its own consensus and execution layers, its own coordinator and realm processors. It bridges to Ethereum because Ethereum is where the world's liquidity sits — not because it needs Ethereum to be a chain.

We treat this as a literal restoration project: the right to transact privately is not a feature, it is a baseline that modern cryptography finally lets us put back where it belongs.

过去五十年统治世界的支付网络,其信任来自同一种方式——把一切都公开。每一张清算的支票、每一次行间转账、 每一笔稳定币交易,都躺在一本任何凭证持有人都能翻阅、任何执法令状都能拿走的账本里。 我们把这视为"经济能够运转"所必须付出的代价。它并不是。 它只是"我们还没有一套足够好的密码学"所付出的代价。

Psy 就是那套密码学终于到来时所能构建出的世界。 建立在 Goldilocks 域上的递归零知识证明,让我们能够发出一种新的支付回执: 它同时是普世可验证的、又是彻底私密的。 外界可以确认你的转账格式正确、余额足够、收款方已注册、系统不变量仍然成立—— 却无从知道你是谁、付给了谁、付了多少。

承托这份承诺的链不能只是"以太坊的隐私版本"。 一条隐私 rollup 如果还把每个区块的成本付给一条公共宿主链, 它就继承了宿主链的经济、延迟与审查面。 Psy 是一条独立的公链:拥有自己的验证者集合、共识与执行层、自己的协调器与 realm 处理器。 它向以太坊桥接,是因为以太坊目前承载着世界的流动性, 而不是因为它需要以太坊才能成为一条链。

我们把这件事当作一种字面意义上的"修复工程": 私下交易的权利不是某种功能,而是一种基线; 现代密码学终于让我们有办法把它放回它本该在的位置。

No. 2

System Overview

/ 系统概览

A Psy chain is composed of three classes of process, two bridge contracts on Ethereum, and one canonical configuration document distributed via a content-addressed page server. Each class has a single, sharply-scoped responsibility, and they communicate exclusively through three message buses: ScyllaDB for durable cold state, Redis for hot per-checkpoint state, and NATS JetStream for ordered job streams.

On the Ethereum side, two Ethereum contracts hold the chain's anchor: a Bridge that accepts Ethereum-side deposits and emits a Deposit event, and a StateManager that ingests recursive rollup proofs and emits a FinalizedBatch event when a new state-transition has been verified on-chain. Together they constitute the cryptographic settlement layer.

Off-chain, three Rust services co-operate per realm: a processor that sequences user requests into checkpoint-sized batches, an edge that serves JSON-RPC to wallets and indexers, and one or more workers that consume jobs off NATS and emit Plonky2 proofs. A single coordinator aggregates realm output and submits the rollup proof to Ethereum.

一条 Psy 链由三类进程、两份以太坊合约、以及一份通过内容寻址页面服务器分发的"权威配置文档"组成。 每一类进程承担单一、范围严格的职责,彼此之间只通过三条消息总线沟通: ScyllaDB 承担持久化冷状态,Redis 承担热的、按 checkpoint 切片的运行时状态, NATS JetStream 承担有序的任务流。

在 以太坊侧,两份合约共同支撑整条链的锚点:Bridge 合约负责接收 以太坊存款并发出 Deposit 事件;StateManager 合约接收来自 Psy 的递归 rollup 证明, 在链上完成验证后发出 FinalizedBatch 事件。两者共同构成密码学结算层。

在链下,每个 realm 由三类 Rust 服务协同:processor 负责把用户请求按 checkpoint 大小切批;edge 向钱包和索引器暴露 JSON-RPC 接口; 一个或多个 worker 从 NATS 拉任务并产出 Plonky2 证明。 单个 coordinator 聚合所有 realm 的输出,并把 rollup 证明递交到以太坊。

           ╭──────────────────────────────────────────────────────────────╮
           │                          ETHEREUM                         │
           │  ┌──────────────┐    ┌─────────────────┐    ┌──────────────┐ │
           │  │   Bridge     │    │  StateManager   │    │ TokenFaucet  │ │
           │  │ deposit()    │    │ submitProof()   │    │ Manager      │ │
           │  └──────┬───────┘    └────────┬────────┘    └──────────────┘ │
           │   Deposit event       FinalizedBatch event                   │
           ╰─────────┼──────────────────────┼─────────────────────────────╯
                     │                      ▲
                ┌────▼────┐         ┌───────┴────────┐
                │ Indexer │         │  Ethereum Submitter  │  (off-chain relayer)
                │ (Envio) │         │  daemon        │
                └────┬────┘         └───────▲────────┘
                     │                      │
           ╭─────────┼──────────────────────┼─────────────────────────────╮
           │         │      PSY  CHAIN      │                             │
           │         ▼                      │                             │
           │  ┌──────────────────────────────────────────┐                │
           │  │              COORDINATOR                 │                │
           │  │   processor · edge · worker(s)           │                │
           │  │   aggregates realm proofs                │                │
           │  └────────┬───────────────────────┬─────────┘                │
           │           │                       │                          │
           │     ┌─────▼──────┐          ┌─────▼──────┐                   │
           │     │  REALM 0   │          │  REALM 1   │   …  (N realms)   │
           │     │ processor  │          │ processor  │                   │
           │     │ edge       │          │ edge       │                   │
           │     │ worker(s)  │          │ worker(s)  │                   │
           │     └─────┬──────┘          └─────┬──────┘                   │
           │           │                       │                          │
           │   ┌───────┴────────┐     ┌────────┴───────┐                  │
           │   │   ScyllaDB     │  …  │    Redis       │   …  NATS JS    │
           │   │ (cold state)   │     │ (hot state)    │   (job streams) │
           │   └────────────────┘     └────────────────┘                  │
           ╰──────────────────────────────────────────────────────────────╯

Field

Goldilocks (p = 2⁶⁴ − 2³² + 1)

Hash

Poseidon · 12-width

Proof system

Plonky2 · recursive

State tree height

32 (per contract)

Realm topology

2 active · up to 128

Cold store

ScyllaDB · 6.0

Hot store

Redis · 7.x

Job bus

NATS JetStream

No. 3

The Three Layers

/ 三层结构

Every Psy chain is structured as three concentric layers: Coordinator, Realm, and Worker. Each layer has its own checkpoint clock, its own database namespace, and its own circuit manager. They are deliberately under-coupled: a misbehaving worker cannot freeze a realm, a stalled realm cannot freeze the coordinator, and the coordinator can produce empty checkpoints even when both realms have nothing to say.

The coordinator is the chain's clock. Its processor wakes on a 100 ms slot tick and, every sixtieth slot (i.e. every 6 s), opens a new checkpoint. It gathers whatever Global-User-Tree-Aggregate (GUTA) proofs, register- user proofs, and deploy-contract proofs the realms have delivered since the last checkpoint, recursively aggregates them into a single rollup state-transition proof, writes the new state root to durable storage, and prints a FinalizedBatch-ready bundle on the side.

Realms hold the per-user state. Every user is permanently assigned to exactly one realm by the high bits of their user_id. Realms run their own processor / edge / worker triad and produce state-transition proofs that the coordinator can absorb. The current production topology uses two realms (group_realm_height = 1); the protocol supports up to 128 (group_realm_height = 7).

Workers are stateless proving servers. They subscribe to NATS subjects for the realm or coordinator that hired them, pull jobs by queue_key, and stream completed proofs back. A worker holds its own copy of every circuit it might be asked to prove — typically several gigabytes of pre-built circuit data per process — and is horizontally scalable: add more workers, the chain proves faster.

每条 Psy 链都呈现为三层同心结构:协调器(Coordinator)realmworker。 每一层都有自己的 checkpoint 时钟、自己的数据库命名空间、自己的电路管理器。 它们之间被刻意做成了"松耦合":一个 worker 行为异常无法冻结 realm, 一个 realm 停摆无法冻结协调器,协调器即使两个 realm 都没话说时仍可以产出空 checkpoint。

协调器是链的时钟。其 processor 每 100 ms 一个 slot 滴答唤醒, 每六十个 slot(即每 6 秒)开启一个新 checkpoint。 它收集 realm 自上一 checkpoint 以来递交的全局用户树聚合证明 (GUTA)、 注册用户证明、部署合约证明,把它们递归地聚合为单一的汇总状态迁移证明, 将新状态根写入持久存储,并在旁路生成一份 FinalizedBatch 准备好的提交包。

Realm 持有按用户切分的状态。 每个用户由其 user_id 的高位永久分配到某个 realm。 Realm 内部同样运行 processor / edge / worker 三件套, 并产出可被协调器吸收的状态迁移证明。 目前生产拓扑使用两个 realm(group_realm_height = 1), 协议本身最多支持 128 个 realm(group_realm_height = 7)。

Worker 是无状态的证明节点。 它们订阅所属 realm 或协调器的 NATS 主题,按 queue_key 拉取任务, 把已生成的证明回流。每个 worker 进程持有一整套自己可能被要求证明的电路—— 每个进程数 GB 的预构建电路数据——并具备水平可扩展性:worker 加得越多,链的证明速度越快。

The conversation between layers / 三层之间的对话

             slot_ms = 100        block_period_slots = 60
             ───────────────────────────────────────────
COORDINATOR  │ tick │ tick │ tick │ … │ process_block()│ tick │
             ───────────────────────────────────────────
                                            │
                                            ▼  publish jobs to NATS
   REALM 0   ─ slot 40 ─ build_block ──▶  ┐
                                          │   workers pull job
   REALM 1   ─ slot 40 ─ build_block ──▶  ├──▶ prove(circuit, witness)
                                          │
   WORKER(s) ─ subscribe(queue_key) ◀─────┘
                                          │
                                          ▼
            recursive aggregation proof returned to coordinator
                                          │
                                          ▼
                       commit_state(new_root, agg_proof)
                                          │
                                          ▼   (off-chain submitter)
                     StateManager.submitFinalizedBatch( … )
No. 4

The Recursive Proof System

/ 递归证明系统

Psy proves over Plonky2, Polygon Zero's FRI-based proof system, instantiated on the Goldilocks field (p = 2⁶⁴ − 2³² + 1) and the Poseidon hash with rate-8 / capacity-4 (12 field elements wide). The choice is not aesthetic. Goldilocks multiplies in two CPU cycles. Poseidon over Goldilocks gives ≈250 ns per permutation on commodity x86. Together they let a wallet on a laptop generate a privacy-preserving transaction proof in 600 ms–2 s, which is the only number that ever mattered.

Plonky2's killer feature is recursive verification at native speed. A circuit that verifies another Plonky2 proof is itself a Plonky2 circuit of bounded size — about 2¹⁶ gates — so the work to aggregate a thousand per-user-tx proofs into a single rollup proof is the same as the work to aggregate two. We exploit this aggressively. The proof a coordinator submits to Ethereum is a recursive tower:

  1. per-user end-cap proofs (one per signing event)
  2. per-realm GUTA aggregate (one per checkpoint per realm)
  3. cross-realm coordinator aggregate (one per checkpoint)
  4. checkpoint state-transition proof (one per checkpoint)
  5. Ethereum-friendly Groth16 wrapper (one per submission)

The final Groth16 wrap is the only step that touches Ethereum. Verifying a Groth16 proof on Ethereum costs ≈250 k gas regardless of how many user transactions hid behind it. Today a checkpoint settles a few hundred user actions per wrap. Tomorrow it will settle a few hundred thousand. The gas line is flat.

Psy 的证明系统选择 Plonky2——Polygon Zero 团队的基于 FRI 的证明系统, 落在 Goldilocks 域p = 2⁶⁴ − 2³² + 1)上, 配以 Poseidon 哈希(rate-8 / capacity-4,12 元素宽)。 这不是审美问题。Goldilocks 上的乘法只要 2 个 CPU 时钟周期; Goldilocks 上的 Poseidon 在普通 x86 上每次置换 ≈ 250 纳秒。 这套组合可以让一台笔记本上的钱包在 600 ms–2 s 内生成一个隐私保护交易证明—— 而这是唯一真正重要的指标。

Plonky2 真正杀手锏的特性是"以原生速度验证另一个 Plonky2 证明"。 一个用于验证 Plonky2 证明的电路,本身就是一个有界大小的 Plonky2 电路 ——大约 2¹⁶ 个 gate——因此把一千条用户交易的证明聚合成一个 rollup 证明, 与聚合两条所需的工作量相同。我们极度激进地利用这一点。 协调器最终递交到以太坊 的证明,本质上是一座递归塔:

  1. 每用户的 end-cap 证明(每签名一次产生一条)
  2. 每个 realm 内的 GUTA 聚合证明(每 checkpoint 每 realm 一条)
  3. 跨 realm 的协调器聚合证明(每 checkpoint 一条)
  4. checkpoint 状态迁移证明(每 checkpoint 一条)
  5. 以太坊友好的 Groth16 包装证明(每次提交一条)

只有最后一层 Groth16 包装会接触以太坊。 在以太坊上验证一个 Groth16 证明大约 ≈ 250 k gas, 而无论这一次包装内部塞了多少笔用户交易,这个成本都是一样的。 今天,一个 checkpoint 在一次包装里结算几百笔用户操作; 明天,它会结算几十万笔。gas 这条线是平的。

A worked example: simple_transfer / 工作流示例:simple_transfer

Alice sends 13.5 PSY to Bob.

WITNESS (private, never leaves Alice's machine)
  alice_private_key          : Goldilocks⁴   // ZK signing key
  alice_balance_before       : u64
  alice_note_count_before    : u32
  alice_note_root_before     : Goldilocks⁴
  bob_user_id                : u64           // recipient_uid
  amount                     : u64

PUBLIC INPUTS (committed in the proof)
  network_magic              : Goldilocks
  contract_id                : u64           (= 0 = PsyTokenContract)
  method_id                  : u64           (= 354447671 = simple_transfer)
  checkpoint_id              : u64
  alice_pk_hash              : Goldilocks⁴   // identity commitment

CONSTRAINTS PROVED
  - knows preimage of alice_pk_hash under Poseidon
  - alice_balance_before  >=  amount + guta_fee
  - alice_note_root_after ==  Poseidon(alice_note_root_before, (bob_user_id, amount))
  - alice_balance_after   ==  alice_balance_before - amount - guta_fee
  - alice_note_count_after == alice_note_count_before + 1
  - all merkle proofs against state-tree-root match

TIME ON USER LAPTOP
  ≈ 900 ms in WASM (release build, single core)
  ≈ 280 ms native CLI

PROOF SIZE                : 132 KB (Plonky2 native), 2.4 KB (Groth16 wrap)
ON-CHAIN VERIFY COST      : 0 — never lands as a standalone tx
No. 5

State Architecture & Merkle Trees

/ 状态结构与默克尔树

Psy state is organised as a four-level tree-of-trees, where every level is a Poseidon-Goldilocks Merkle tree of fixed depth. The chain's entire global root is a single 32-byte digest. Any merkle path through the structure has a constant number of siblings, and every sibling is a single Goldilocks-quartet (32 bytes). This bounded shape is what lets a wallet prove inclusion in 30 ms on a phone.

  • Global state root. The root of the global user tree. Height = 32. Each leaf is the realm-user-tree-cap of the realm that owns that user_id band.
  • Realm user tree. Height = 20. Each leaf is a single user's “user-contract-tree” cap. Realms shard along the high bits of user_id.
  • User contract tree. Per-user index of every contract that user has touched. Height = 32. Each leaf is the contract-state-tree root of that user under that contract.
  • Contract state tree. Height = 32. Each leaf is a 32-byte slot. Contracts declare their state layout symbolically (sub_slot_index: 6 etc.); the compiler maps each symbolic slot to a leaf position.

In addition to the per-user state, the chain carries two global incremental Merkle trees (IMTs) anchored on Ethereum:

  • Deposit tree. Append-only. Every Ethereum-side Deposit event becomes a leaf Poseidon(recipient, amount, l2_token_contract_id, shield_address, secret) . Psy users prove inclusion to claim.
  • Withdrawal tree. Append-only. Each Psy-side withdrawal initiation appends a leaf; the coordinator submits the new tree root in the next FinalizedBatch, and the user redeems on Ethereum with a merkle proof against that root.

Psy 的状态被组织为"四层嵌套的树中树",每一层都是固定深度的 Poseidon-Goldilocks 默克尔树。 整条链的全局根是一个 32 字节的摘要。 结构中任何一条 merkle 路径,其兄弟节点的数量都是常数, 且每个兄弟节点都是一个 Goldilocks 四元组(32 字节)。 正是这种"有界形状",让一个手机上的钱包能在 30 ms 内完成成员性证明。

  • 全局状态根。这是全局用户树的根,高度 32。 每个叶子是负责那一段 user_id 区间的 realm 的"realm 用户树 cap"。
  • Realm 用户树。高度 20。每个叶子是单个用户的"用户合约树 cap"。 realm 按 user_id 的高位进行分片。
  • 用户合约树。每个用户曾接触过的合约索引。高度 32。 每个叶子是该用户在该合约下的"合约状态树根"。
  • 合约状态树。高度 32。每个叶子是 32 字节槽位。 合约用符号化的方式声明状态布局(sub_slot_index: 6 等), 编译器将每个符号槽映射到叶子的位置。

除此之外,链上还有两棵锚定到以太坊 的全局增量默克尔树(IMT):

  • 存款树(Deposit tree)。仅追加。 每一次 以太坊 Deposit 事件都会成为一个叶子,叶值为 Poseidon(recipient, amount, l2_token_contract_id, shield_address, secret) 。 Psy 用户凭存款树成员性证明进行 claim。
  • 提现树(Withdrawal tree)。仅追加。 每次 Psy 侧发起提现都会追加一个叶子; 协调器会在下一次 FinalizedBatch 中把新树根递交到以太坊, 用户拿着对该根的 merkle 证明在 以太坊完成赎回。

The state tree-of-trees / 状态的树中树

                         ╔════════════════════════════╗
                         ║   GLOBAL  STATE  ROOT      ║   32 bytes
                         ║   (Poseidon, height 32)    ║
                         ╚════════════════════════════╝
                                    │
            ┌───────────────────────┼───────────────────────┐
            ▼                       ▼                       ▼
   ┌────────────────┐      ┌────────────────┐      ┌────────────────┐
   │  REALM 0 cap   │      │  REALM 1 cap   │      │  REALM n cap   │
   │  height 20     │      │  height 20     │      │  height 20     │
   └───────┬────────┘      └────────────────┘      └────────────────┘
           │
   ┌───────┴──────────────────────────────────────────────┐
   ▼                                                      ▼
┌─────────────────────┐                       ┌─────────────────────┐
│  user_contract_tree │   ←── 1 per user      │  user_contract_tree │
│  height 32          │                       │  height 32          │
└──────────┬──────────┘                       └─────────────────────┘
           │
   ┌───────┴─────────────────────────────┐
   ▼                                     ▼
┌───────────────────────┐    ┌───────────────────────┐
│ contract_state_tree   │    │ contract_state_tree   │
│ (for contract id 0    │    │ (for contract id 4    │
│  = PsyToken)          │    │  = USDT)              │
│ height 32 · slot map  │    │ height 32 · slot map  │
└───────────────────────┘    └───────────────────────┘
No. 6

User Identity & Realm Sharding

/ 用户身份与 Realm 分片

A Psy user is identified by a single u64: user_id. The number is not arbitrary — its bit layout encodes which realm owns the user and which sub-tree position the user occupies inside that realm. The layout is set by the chain's configured UserIdBitsStrategy, of which two are in production:

  • Strategy 4 — 128-realm fan-out. group_realm_height = 7, users_per_realm = 2²⁰, total addressable users = 2²⁷ ≈ 134 M. Used by the earlier wide-fan-out deployment.
  • Strategy 5 — 2-realm minimal. group_realm_height = 1, users_per_realm = 2²⁰, total addressable users = 2²¹ ≈ 2 M. Current production topology — gives much cheaper recursive aggregation while the network ramps. Strategy switches are forward-compatible: future hard-forks can promote to Strategy 4 without invalidating user_id space, only reassigning realms.

The realm a user belongs to is user_id / users_per_realm (integer division). The user's position inside the realm user tree is user_id mod users_per_realm. Both numbers are public — there is no privacy gain in hiding which realm a user lives in; the privacy is in what the user does there.

A crucial implication is that realm-side circuits are not interchangeable across strategies. A psy-sdk WASM built against Strategy 4 will produce proofs whose merkle-path arity disagrees with the Strategy 5 state tree, and the realm will reject them. Wallet builds are therefore strategy-tagged, and the bridge ships strategy-specific artifacts in psy-config-stg/config.json.

一个 Psy 用户由单一的 u64 标识:user_id。 这个数字并非任意——它的比特排布编码了"用户属于哪个 realm"和"用户在那个 realm 内占据哪个子树位置"。 这一排布由链上配置的 UserIdBitsStrategy 决定,目前生产中有两种:

  • Strategy 4 — 128 个 realm 横向扩展group_realm_height = 7users_per_realm = 2²⁰, 最大可寻址用户数 = 2²⁷ ≈ 1.34 亿。 早期宽扇出部署所采用的方案。
  • Strategy 5 — 极简 2 realmgroup_realm_height = 1users_per_realm = 2²⁰, 最大可寻址用户数 = 2²¹ ≈ 210 万。 目前生产拓扑——在网络起步阶段,可以显著降低递归聚合成本。 策略切换是向前兼容的:未来硬分叉可以从 Strategy 5 升级到 Strategy 4, 不会让现有 user_id 空间失效,只是重新分配 realm。

用户所属 realm 为 user_id / users_per_realm(整数除法); 用户在该 realm 的用户树内位置为 user_id mod users_per_realm。 这两个数字都是公开的——隐藏"用户在哪个 realm"不会带来隐私收益; 真正的隐私在于用户在那里做了什么

一个关键推论是:不同 strategy 下的 realm 电路并不能互换。 以 Strategy 4 编译的 psy-sdk WASM 所产出的证明,其 merkle 路径分支度 与 Strategy 5 的状态树不匹配,realm 会直接拒绝。 因此钱包构建必须带 strategy 标签, 而桥也会在 psy-config-stg/config.json 中分发 strategy-特定的部署物。

user_id ⇒ realm / user_id 到 realm 的映射

Strategy 5 (group_realm_height = 1, users_per_realm = 1048576)

    user_id =  bits[20]      ||  bits[0..19]
              ─────────────      ───────────────
                realm bit         position in realm

    65536  = 0_0000_0000_0001_0000_0000_0000_0000  →  realm 0, pos   65536  (Alice)
   262144  = 0_0000_0000_0100_0000_0000_0000_0000  →  realm 0, pos  262144  (operator-0)
  1310720  = 0_0001_0100_0000_0000_0000_0000_0000  →  realm 1, pos  262144  (operator-1)
  1835008  = 0_0001_1100_0000_0000_0000_0000_0000  →  realm 1, pos  786432

Strategy 4 (group_realm_height = 7, users_per_realm = 1048576)

    user_id =  bits[20..26]      ||  bits[0..19]
              ───────────────       ───────────────
                  realm (7-bit)        position in realm

    realm count = 2⁷ = 128
No. 7

Block Production Lifecycle

/ 区块生产生命周期

A Psy “block” is a tuple: (checkpoint id, rollup state-transition proof, aggregate realm caps). The coordinator's runner loop fires every 6 seconds and walks the pipeline. Below is the actual structure of coordinator/processor/core/process_block.rs:

  1. get_results_from_gatherers() — pull each realm's submitted GUTA, register-user, and deploy-contract job IDs that landed since the last checkpoint.
  2. get_root_job_ids() — if every job slot holds a dummy circuit type (GUTANoChange, DummyAppendUserRegistrationTreeAggregate, DummyBatchDeployContractsAggregate), return Ok(None); the chain is idle this tick.
  3. publish_jobs(level=0) — write the per-realm proof jobs to NATS for workers to pick up.
  4. plan_genesis_checkpoint_state_transition_proof()— only on checkpoint_id == 0.
  5. plan_agg_guta_register_users_deploy_contracts_job()— schedule the recursive aggregation that will combine the per-realm proofs.
  6. wait_for_jobs_completion() — block until the level-0 proofs are back.
  7. publish_jobs(level=1..) — push the next recursion layer.
  8. publish_and_wait_for_job_completion(agg_job)— finalise the cross-realm aggregate.
  9. plan_checkpoint_state_transition() — fold the realm caps into a new global root + Plonky2 state- transition proof.
  10. commit_state() — persist the new root and proof; print Committed new coordinator block with checkpoint_id = N.

Psy 的"区块"是一组三元组:(checkpoint id汇总状态迁移证明realm cap 聚合)。 协调器的 runner 循环每 6 秒触发一次,沿着流水线推进。 以下是 coordinator/processor/core/process_block.rs 的实际结构:

  1. get_results_from_gatherers()—— 拉取上一 checkpoint 以来各 realm 递交的 GUTA、注册用户、部署合约 job ID。
  2. get_root_job_ids()—— 如果所有 job 槽都装的是哑电路GUTANoChange 等),返回 Ok(None);本 tick 链是空闲的。
  3. publish_jobs(level=0)—— 把按 realm 划分的证明任务投递到 NATS 给 worker 消费。
  4. plan_genesis_checkpoint_state_transition_proof()——仅在 checkpoint_id == 0 时执行。
  5. plan_agg_guta_register_users_deploy_contracts_job()——调度将各 realm 证明合并的递归聚合任务。
  6. wait_for_jobs_completion()——阻塞,直到 level-0 证明回流。
  7. publish_jobs(level=1..)——推送下一层递归。
  8. publish_and_wait_for_job_completion(agg_job)——完成跨 realm 聚合。
  9. plan_checkpoint_state_transition()—— 将各 realm cap 折叠为新的全局根 + Plonky2 状态迁移证明。
  10. commit_state()——持久化新根与证明,打印 Committed new coordinator block with checkpoint_id = N
No. 8

The Ethereum ↔ Psy Bridge

/ Ethereum ↔ Psy 桥

The Psy bridge is a pair of one-way pipes: an ingress that pulls Ethereum ERC-20 balances into Psy as shielded notes, and an egress that returns Psy balances to Ethereum ERC-20s. Both directions are non-custodial in the cryptographic sense — the bridge contract holds custody of tokens but cannot move them without a valid Plonky2 proof of Psy-side intent. The two directions ride two independent Merkle trees.

Ingress — Ethereum → Psy.The user calls Bridge.deposit(token, amount, recipient_user_id, secret) on Ethereum. The contract pulls the ERC-20 via an approve+transferFrom, hashes Poseidon(recipient, amount, l2_token_contract_id, shield_address, secret) into a leaf, appends it to the deposit IMT, and emits a Deposit event. The off-chain indexer ingests the event, the the relayer folds the new deposit-tree-root into the next coordinator checkpoint, and from that checkpoint onward the recipient can run claim_deposit, proving inclusion of their leaf in the published root and crediting themselves the amount privately.

Egress — Psy → Ethereum.The user runs initiate_withdraw(token, amount, l1_recipient) on Psy. This burns the Psy-side balance and appends a leaf Poseidon(l1_recipient, amount, l2_token_contract_id, nonce) to the withdrawal IMT. The next coordinator checkpoint that lands on Ethereum carries the new withdrawal-tree-root. The user (or anyone, since the Ethereum-side transaction has no authority requirement beyond merkle inclusion) calls StateManager.completeWithdrawal(merkleProof, leaf), the contract verifies inclusion against the latest finalized root, and the ERC-20 is released to l1_recipient.

The whole thing has exactly one trust assumption: that the Ethereum's Groth16 verifier accepts only proofs corresponding to honestly-computed Psy state transitions. As soon as that proof verifies, all downstream tree roots are consensus-pinned, and there is no “optimistic challenge window.” Withdrawals are instant in the sense that there is no fraud-proof delay; the only delay is the proving time of the checkpoint that includes them, currently ≈90 s.

Psy 的桥由两条单向管道组成:入向把 以太坊上的 ERC-20 余额拉入 Psy 成为屏蔽笔记;出向把 Psy 余额送回成 以太坊上的 ERC-20。 两个方向在密码学意义上都是非托管的—— 桥合约托管代币,但若没有合法的 Psy 侧意图的 Plonky2 证明,它自己也动不了一分钱。 两个方向各自走一棵独立的默克尔树。

入向 Ethereum → Psy。 用户在以太坊上调用 Bridge.deposit(token, amount, recipient_user_id, secret)。 合约通过 approve + transferFrom 拉走 ERC-20, 将 Poseidon(recipient, amount, l2_token_contract_id, shield_address, secret)哈希为一个叶子追加到存款 IMT,发出 Deposit 事件。 链下索引器消化该事件,Psy 侧的中继器把新的存款树根折入下一个协调器 checkpoint。 从那一刻起,收款方就可以调用 claim_deposit, 提交叶子相对发布根的成员性证明,将金额私密地记到自己名下。

出向 Psy → Ethereum。 用户在 Psy 上调用 initiate_withdraw(token, amount, l1_recipient), 销毁 Psy 侧余额并将一个 Poseidon(l1_recipient, amount, l2_token_contract_id, nonce) 叶子追加到提现 IMT。 下一次协调器 checkpoint 落到以太坊 时,会带上新的提现树根。 之后任何人(以太坊上的这一笔交易除"merkle 成员性"外无任何权限要求)都可以调用 StateManager.completeWithdrawal(merkleProof, leaf), 合约对最新已 finalize 的根做成员性验证,将 ERC-20 释放给 l1_recipient

这整套机制只有一条信任假设:以太坊上的 Groth16 verifier 只接受真正诚实计算出的 Psy 状态迁移证明。 只要那一份证明被链上验证通过,所有下游的树根都被共识固定,没有"乐观挑战窗口"这种概念。 提现是即时的——在"无需等欺诈期"的意义上; 唯一的延迟来自包含该提现的 checkpoint 自身的证明时间,目前约 90 秒。

No. 9

Privacy Layer

/ 隐私层

Privacy on Psy is layered. A user can choose to operate publicly (simple_transfer / simple_claim) at lowest proving cost, or to operate privately (private_transfer, claim_deposit with shield-address) at the cost of a slightly larger circuit. The same chain runs both. The same user can mix and match per-payment. Everything below is implemented in production today.

Shielded notes. A private balance is a set of notes, each note being a Poseidon commitment to (value, asset, owner_secret, nonce). The note tree is per-user. To spend a note, the sender publishes its nullifier Poseidon(owner_secret, nonce) — and proves in zero-knowledge that the nullifier corresponds to a committed note inside the global note tree. The receiver receives one or more new notes whose commitments are appended to their own note tree.

Sign types. Authentication is plural. Psy ships five circuit families that authorize a tx, selectable per-key:

  • ZKSign — Poseidon-Goldilocks Schnorr. Default for end-user wallets. Smallest circuit.
  • SECP256K1Sign — for compatibility with Ethereum keys (think: log in with MetaMask, spend on Psy).
  • SoftwareDefinedDPNSign, SoftwareDefinedPlonky2Sign — escape hatches for application-specific signing rules (multisig, social recovery, time-locks).
  • SDKKeySign — “allow-method” delegated keys. The signing key is provably restricted to specific (contract_id, method_id) pairs and a per-key transaction count. The fingerprint baked into the circuit commits to those constraints. Used by the public faucet (No. 10).

The allow-method circuit. An SDK-key fingerprint is the Poseidon hash of the circuit that enforces this key can sign only these (contract, method) pairs and at most N times. The wallet locally re-builds that circuit (via register_sdk_key_circuit(contract_ids[], method_ids[], expected_tx_count)), gets the same fingerprint, and uses it to import its private key under the SDK-key sign type. This lets a backend hand out short-lived, narrowly-scoped signing keys without ever holding user funds.

Psy 上的隐私是分层的。 用户可以选择"公开"地操作(simple_transfer / simple_claim), 以最低证明成本完成支付; 也可以选择"私密"地操作(private_transfer, 配合 shield-address 的 claim_deposit), 以略大的电路成本换取完整匿名。 同一条链同时跑这两套;同一个用户可以按支付情况自由混用。 以下机制全部已在生产环境实现。

屏蔽笔记(Shielded notes)。 一个私密余额是若干笔记构成的集合, 每一笔记是对 (value, asset, owner_secret, nonce) 的 Poseidon 承诺。 笔记树按用户维度维护。要"花掉"一笔记,发送方公布它的无效化符 (nullifier)—— Poseidon(owner_secret, nonce) —— 并以零知识证明该无效化符对应于全局笔记树中已承诺的某笔记。 收款方则收到一或多张新笔记,其承诺被追加到自己的笔记树中。

签名类型。 身份认证不是单一的。Psy 出厂提供五个用于授权一笔交易的电路家族,可按密钥级别选用:

  • ZKSign——Poseidon-Goldilocks 的 Schnorr。 终端用户钱包默认。电路最小。
  • SECP256K1Sign——为兼容以太坊密钥而设 (想想:用 MetaMask 登录,在 Psy 上花钱)。
  • SoftwareDefinedDPNSign SoftwareDefinedPlonky2Sign—— 应用自定义签名规则的逃生口(多签、社交恢复、时间锁等)。
  • SDKKeySign——"allow-method" 委派密钥。 签名密钥在密码学上被限制为只能签特定的 (contract_id, method_id) 对, 且总交易次数有上限。 电路指纹本身就承诺了这些约束。公共水龙头即基于此(参见 No. 10)。

allow-method 电路。 SDK-key 的指纹,就是"强制本密钥只能签这些 (contract, method) 对、至多 N 次"这一电路本身的 Poseidon 哈希。 钱包本地通过 register_sdk_key_circuit(contract_ids[], method_ids[], expected_tx_count) 重新构造同样的电路,得到同样的指纹, 然后以 SDK-key 签名类型导入私钥。 这让后端可以发放"短生命周期、严格作用域受限"的签名密钥, 却从不必托管任何用户资金。

No. 10

Faucet & Demand-Creation Layer

/ 水龙头与需求创造层

The Psy testnet faucet is a small but instructive cryptosystem in its own right. It demonstrates two things at once: (1) that an in-browser WASM signer can drive arbitrary contract calls without a backend, and (2) that the SDK-key sign type can replace custodial key-management for a public throughput surface.

Topology. Ten operator wallets are bundled into the bridge frontend, each pre-funded with 1 000 000 PSY. All ten share the same circuit fingerprint — they were registered against one register_sdk_key_circuit([faucet_contract_id], [faucet_method_id], expected_tx_count=3) call — which means a single in-tab WASM session loads one circuit and uses it to sign for any of the ten.

Rotation. When a user clicks “Claim,” the bridge picks operator recipient_user_id mod 10. Same recipient always hits the same operator. This stable, per-recipient pinning is what makes the faucet contract's per-pair rate limit work: the contract tracks “PSY sent from operator i to recipient j in the last 120 checkpoints”, caps it at 1 000 PSY, and because each recipient maps to exactly one operator, the cap is enforced naturally.

Honest-client caveat. Because the ten private keys are bundled in the browser, a motivated user can extract them and call the faucet from all ten operators simultaneously, multiplying the cap 10×. Defence is contract-side: aggregate the cap on the recipient side rather than per-pair, or move the signing to a server that gates by recipient regardless of which operator key signed. For a testnet faucet this is acceptable; for any production economy it would not be.

Psy 测试网水龙头本身就是一套小而精的密码系统。 它同时演示了两件事: (1) 浏览器内的 WASM 签名器可以在不依赖任何后端的情况下驱动任意合约调用; (2) SDK-key 签名类型可以替代传统托管式密钥管理,承担"公共吞吐入口"的职责。

拓扑。 十个 operator 钱包打包在桥的前端,每个预存 100 万 PSY。 十个共享同一个电路指纹—— 它们都登记在同一次 register_sdk_key_circuit([faucet_contract_id], [faucet_method_id], expected_tx_count=3) 调用之下—— 这意味着浏览器中一次 WASM session 只加载一个电路,就能为这十个中的任何一个签名。

轮转。 用户按下 "Claim" 时,桥按 recipient_user_id mod 10 选 operator。 同一个收款方永远落在同一个 operator。 这种"按收款方稳定钉死"的策略,让水龙头合约对每对 (sender, recipient) 的速率限制真正生效: 合约只追踪"过去 120 个 checkpoint 内 operator i 向 recipient j 转了多少 PSY", 上限 1000 PSY;而由于每个收款方只对应一个 operator,上限被自然强制。

诚实客户端假设的代价。 由于十把私钥都打包在浏览器里,一个有动机的用户可以把它们提取出来, 同时从十个 operator 各调用一次水龙头——把上限放大 10 倍。 防御应在合约侧:把上限聚合在收款方一侧而非按对计算; 或者把签名移到一台仅按收款方限速、不在意是哪把 operator 钥签的服务器上。 对测试网水龙头这种情况是可以接受的;对任何生产经济体则不可接受。

The two-click claim path / 两次点击的领取路径

Click 1  (operator → in-tab WASM, no wallet popup)
  ┌────────────────────────────────────────────────────────────────┐
  │ 1. pickOperatorFor(uid)           //  i = uid mod 10            │
  │ 2. register_sdk_key_circuit([fc], [fm], 3)   // once per session│
  │ 3. importPrivateKey(op_i.sk, "sdk-key", fingerprint)            │
  │ 4. provider.sendTransaction(                                    │
  │       contract_id = 5,                                          │
  │       method     = "faucet",                                    │
  │       inputs     = [uid, 1000_PSY],                             │
  │       pk_hash    = op_i.address,                                │
  │    )                                                            │
  │ 5. wait_for_user_nonce_change(op_i, +240s)                      │
  └────────────────────────────────────────────────────────────────┘

Click 2  (user wallet popup signs simple_claim)
  ┌────────────────────────────────────────────────────────────────┐
  │ 6. psySession.execContractCall(                                 │
  │       contract_id = 0,                                          │
  │       method     = "simple_claim",                              │
  │       inputs     = [op_i.userId],                               │
  │    )                                                            │
  │ 7. balance += 1000 PSY (minus guta_fee)                         │
  └────────────────────────────────────────────────────────────────┘
No. 11

Tooling Stack

/ 工具栈

Five user-facing surfaces sit on top of the chain. Each is independently deployable, each speaks the same JSON-RPC, and each ships its own copy of the Plonky2 WASM prover so it can construct proofs without round- tripping a server.

psy-walletChrome MV3 extension · in-tab prover · ZK + SDK-key
Holds user keys locally. Signs every tx with a Plonky2 proof generated inside the extension's background page via the bundled WASM. No private key ever leaves the extension; the dapp only sees signed payloads.
psy-sdkTypeScript + Rust → WASM · the lingua franca
The Rust crate psy-rust-sdk compiled to WASM, plus a TypeScript wrapper exposing createMemoryWalletProvider, register_sdk_key_circuit, deposit / withdraw helpers, and full local proving.
psy-bridge / privacy-bridge demoThe reference dapp
Lets a user deposit USDT or ETH from Ethereum and claim it as a shielded balance on Psy, send privately, withdraw back. Reference for every other dapp.
psy-explorerVite + React block explorer
Indexed entirely off Ethereum FinalizedBatch events plus realm RPC fan-out. Two views: per-checkpoint, per-user. Shows realm 0/1 lag, deposit / withdrawal queues, contract leaderboard.
psy-ideBrowser IDE for Psy-lang contracts
Edits, compiles (via the dargo WASM compiler), tests in a sandboxed devnet, and deploys to the connected network — all in the browser, no toolchain.

链之上有五个面向用户的入口。 它们各自可独立部署,统一说同一份 JSON-RPC 协议, 并各自打包一份 Plonky2 WASM 证明器,使得它们都能在不往返任何服务器的情况下本地生成证明。

psy-walletChrome MV3 扩展 · 标签页内证明器 · ZK + SDK-key
在本地持有用户密钥。每笔交易在扩展的 background page 内通过打包好的 WASM 生成 Plonky2 证明。 私钥从不出扩展边界,DApp 只看到已签好的负载。
psy-sdkTypeScript + Rust → WASM · 通用语言
Rust 工程 psy-rust-sdk 编译为 WASM, 外加一层 TypeScript 包装: createMemoryWalletProvider register_sdk_key_circuit、 存款 / 取款工具方法,以及完整的本地证明能力。
psy-bridge / 隐私桥示例参考 dApp
允许用户从以太坊存入 USDT 或 ETH,作为屏蔽余额到达 Psy,私密发送,最终取回。 是所有其他 dApp 的参考实现。
psy-explorerVite + React 区块浏览器
完全基于 Ethereum FinalizedBatch 事件 + realm RPC 扇出索引。 两种视图:按 checkpoint、按用户。 展示 realm 0/1 lag、存款 / 提现队列、合约榜。
psy-ide浏览器中的 Psy-lang 合约 IDE
在浏览器里编辑、用 dargo WASM 编译器编译、在沙盒 devnet 中测试、向所连网络部署—— 全程不需要任何本地工具链。
No. 12

Forward — The AI-Scale Endgame

/ 未来 — AI 规模的终局

Psy is built for a world where the dominant payer is not a human. In ten years, the vast majority of micropayments originated on this planet will be issued by autonomous software acting on behalf of humans — agents purchasing inference, agents purchasing data, agents reconciling expenses with other agents. The defining property of that world is not throughput. It is privacy by default, because the alternative is a panopticon in which every model on Earth can watch every model on Earth spend money, and the strategic implications of that visibility are ruinous.

The architectural commitments below are what the next eighteen months of Psy look like, in order of landed:

  • Cached identity proofs for idle blocks — let the coordinator re-use a pre-proved no-change proof across empty checkpoints instead of re-proving the same tautology each tick. Expected effect: idle-block cadence drops from the current ~90 s into the single- digit-second range.
  • Realm fan-out to 128 via Strategy 4 promotion. Each realm runs an independent proving worker pool; aggregation at the coordinator remains O(log N) recursive. Throughput scales near-linearly with number of realms.
  • Multi-coordinator BFT — today one coordinator owns the checkpoint clock. The next generation pushes coordinator election to a BFT committee, removing the single-operator censorship surface. Internally this is “coordinator becomes a contract.”
  • Universal SDK-key marketplace. Today SDK-keys are used inside one product (the faucet); the primitive generalises to a public market of “agents holding allow-method keys for specific dapps.” A user can mint a key that lets an AI model spend up to ¥100 of stable on inference at a specific provider, for a week, and revoke it by burning the corresponding fingerprint nullifier.
  • Compliance bridges. Public-input selective disclosure: a user can choose to reveal, under a specific regulatory key, the recipient or amount of a single transaction, without breaking privacy for any other transaction. Closes the “cannot satisfy a subpoena” objection without re-introducing surveillance by default.
  • Sub-millisecond settlement on Ethereum. Migrate the Groth16 wrap to a verifier deployed on EthDA-class chains where the calldata cost is ≈10× lower. Final goal: a Psy checkpoint costs less to anchor than a single Ethereum transfer.

The closing claim of this treatise is the same as its opening: the right to transact privately is a baseline, not a feature. Math has finally made it cheap. Psy is the engineering vehicle that puts it back where it belongs.

Psy 是为这样一个世界而造的:这个世界里,最大宗的付款人不是人类。 十年之内,地球上发生的绝大多数微支付,将由代表人类的自主软件发起—— 代理购买推理、代理购买数据、代理与其他代理结算费用。 那个世界的核心特征不是吞吐,而是默认隐私。 因为若不默认私密,则地球上每一个模型都能看见地球上每一个模型如何花钱, 而这种可见性的战略后果是灾难性的。

下面是 Psy 未来十八个月的工程承诺,按预计落地顺序排列:

  • 空块的缓存恒等证明—— 让协调器对所有空 checkpoint 复用一份预先证明好的 no-change 证明, 而不必每个 tick 都把同一条恒等式重新证一遍。 预期效果:空闲出块周期由当前的 ~90 秒,降到个位数秒级。
  • Realm 横向扩展到 128,通过升级到 Strategy 4 实现。 每个 realm 独立运行证明 worker 池; 协调器侧的聚合保持 O(log N) 递归。 吞吐随 realm 数近线性扩展。
  • 多协调器 BFT。 目前 checkpoint 时钟由单一协调器掌控。 下一代将把协调器选举推到 BFT 委员会, 消除"单一运维者审查"这一攻击面。 内部说法是"协调器要变成合约"。
  • SDK-key 普惠市场。 今天 SDK-key 仅在某个产品(水龙头)内部使用; 这一原语可一般化为"持有特定 dapp 的 allow-method 密钥的代理"的公开市场。 用户可以铸造一把密钥:让某个 AI 模型在某家推理供应商处至多花掉 ¥100 稳定币、为期一周; 撤销时,只需销毁对应的指纹无效化符即可。
  • 合规桥。 公开输入的选择性披露: 用户可在特定监管密钥下,披露某一笔交易的收款方或金额, 而不破坏其他任何交易的隐私。 把"传票无法被满足"这一反对意见关掉, 而不引入"默认全监控"。
  • 以太坊上的亚毫秒级结算。 将 Groth16 包装迁移到 calldata 成本 ≈10× 低的 EthDA 级链。 终极目标:一次 Psy checkpoint 锚定到以太坊 的成本,比一次以太坊转账还便宜。

本论以同一句话开篇,亦以同一句话收束: 私下交易的权利是基线,不是功能。 数学终于让它变得便宜。 Psy 是把它放回它本该在的位置的工程载体。