winsznx/nulth
GitHub: winsznx/nulth
Nulth 是一个基于 Stellar 的零知识证明授权智能账户,只有当链下生成的 Groth16 证明满足隐藏的支出策略时,链上资金才会发生转移。
Stars: 1 | Forks: 1
# Nulth
**针对公共资金的隐私控制。**
Nulth 是一个经证明授权的 Stellar 账户:它只有在以零知识证明该支付遵守了链上从未见过的规则时才能进行支付。它的签名*就是*证明。
`65,536 个隐私白名单插槽 · 在 Stellar 交易计算预算的 8.537% 内完成验证 · 已在 Stellar 测试网运行`
## 链上实况
### 测试网 (Protocol 26)
| 合约 | ID |
|---|---|
| Nulth 账户 (无密钥,经 ZK 授权) | [`CANA5QYVHNON7AV752ZRATFW2T5BMS3MU5DDPJMU5UGSR3KSH45LOGZE`](https://stellar.expert/explorer/testnet/contract/CANA5QYVHNON7AV752ZRATFW2T5BMS3MU5DDPJMU5UGSR3KSH45LOGZE) |
| BN254 Groth16 验证器 | [`CCKBPVP7MZJOQYU44RK5MG4PA2YKV4UQ7CJMPK3OIHNFHLG5PEMNDREG`](https://stellar.expert/explorer/testnet/contract/CCKBPVP7MZJOQYU44RK5MG4PA2YKV4UQ7CJMPK3OIHNFHLG5PEMNDREG) |
| 支付资产 | 权威的 Circle 测试网 USDC (`GBBD47IF…ZLLFLA5`) |
来自该账户的证明授权 USDC 支付(浏览器证明 → USDC 转账):[`24ce435e…0677`](https://stellar.expert/explorer/testnet/tx/24ce435e822caa5961913ca1a98491d413bf18309857164b10c42e3ab0650677) — **完全**由 ZK 证明授权;策略外的目的地会被拒绝(见证中断,无交易)。
### 主网
特意在外部审查之前暂缓。Nulth 是一种全新的授权层面,因此主网部署需等待审计(SCF Audit Bank 是其途径)。上述所有内容目前均在测试网上运行,包含真实的证明授权 USDC —— 这是出于成熟的谨慎,而非缺失工作。
## 立即运行测试
```
# Contract — 34 个测试,所有不同的 error codes
cargo test --manifest-path contracts/Cargo.toml
# Circuit — 7 个测试(policy + disclosure,有效 + 无效 witnesses)
cd circuits && npm test
# End-to-end — 5 个 headless drivers 对接 live testnet
bash scripts/run_e2e.sh
```
**对抗性测试矩阵** — 每个可达的 `AccError` 都是经过测试的阴性对照,具有不同的代码:
| 测试 | 攻击 | 预期 | 代码 | 状态 |
|---|---|---|---|---|
| `test_valid_proof_authorized` | 正常路径 | 执行转账 | — | ✅ |
| `test_bad_proof_swapped_ac` | 交换 Groth16 A/C | `BadProof` | #3 | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/6d40f77b9f3480f0e4af829efb2922308368eb64300996efc2d509eecc52aec3) |
| `test_old_policy_binding` | 证明对比轮换后的策略 | `BadPolicyBinding` | #4 | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/fc9b3e4304dc54751d192b446967f3180d48eadf26e3481deee66745ba0b1ac5) |
| `test_amount_binding` | 金额 ≠ 证明信号 | `BadAmountBinding` | #5 | ✅ |
| `test_dest_binding` | 重定向目的地 | `BadDestBinding` | #6 | ✅ |
| `test_bad_context_burn_fn` | 使用 `burn()` 而非 `transfer()` | `BadContext` | #7 | ✅ |
| `test_from_binding` | from ≠ 账户地址 | `BadFromBinding` | #11 | ✅ |
| `test_amount_too_large` | 金额 ≥ 2¹⁰⁰ | `AmountTooLarge` | #12 | ✅ |
| `test_sigpayload_binding` | 新鲜随机数证明提升 | `BadSigPayload` | #13 | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/bd424c94c879b5a7d4a3a173395b72a45481f355520341fe5d4926a84af27597) |
| `test_malformed_vk_rejected_at_construction` | `vk.ic.len ≠ 7` | `MalformedVk` | #14 | ✅ |
| `test_empty_context_rejected` | 空的 `auth_contexts` | `NoContext` | #15 | ✅ |
| `test_two_contexts_rejected` | 多上下文一揽子授权 | `TooManyContexts` | #16 | ✅ |
| `test_freeze_blocks_valid_proof` | 冻结时支出 | `AccountFrozen` | #17 | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/071294a4d7d05437ef75b38be94bfb95c5d20a79ef02ecdc2bd63b543eded3e3) |
| `test_non_admin_rotate_rejected` | 未经授权的轮换 | host `Error(Auth)` | — ¹ | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/308d140c3c0e1dad80ae7c7d46eed8a4c2bdbb3a75e5f21d20e73a5f97434c75) |
| `test_token_binding` | 错误的代币 (XLM SAC) | `BadTokenBinding` | #10 | ✅ · [链上 FAILED](https://stellar.expert/explorer/testnet/tx/84ba7fbca8319d12f8b88e13f79a85283912227cbe5dcc4294ae414c2284ddba) |
| `test_negative_amount` | `i128::MIN` | `NegativeAmount` | #9 | ✅ |
| `test_bad_signal_count` | 错误的 `pub_signals` 长度 | `BadSignalCount` | #8 | ✅ |
| `test_root_binding` | 错误的 `allowlist_root` | `BadPolicyBinding` | #4 | ✅ |
| 重放 (相同的 auth entry) | 重新提交已结算的 nonce | host `ExistingValue` | — | ✅ · [模拟证据](./docs/reports/REPORT_P1.md) |
¹ 非管理员治理在**宿主机**边界(`admin.require_auth()`)被拒绝,在任何合约主体运行之前 —— 合约代码 `Unauthorized` #18 已被**保留**且永远不会返回。cargo 测试针对不满足的 `require_auth` 设置了 `#[should_panic]`。同样地,`AlreadyInit` #2 也被保留(宿主机强制执行的单次构造函数);**声明的 18 个代码中有 16 个处于活动状态**。
包含交易哈希的完整矩阵:[ADVERSARIAL_TESTING.md](./ADVERSARIAL_TESTING.md)。
## 可复现构建与验证
每个合约的构建都是可复现的,因此任何人都可以确认链上字节来自此源码:
- **确定性构建** — 账户合约源码可逐字节重建其链上 WASM 哈希(`stellar contract build`;rustc 1.94 · stellar-cli 25 · soroban-sdk 26.1.0)。
- **CI 溯源** — [`.github/workflows/release.yml`](./.github/workflows/release.yml) 使用 Stellar Expert 的 `soroban-build-workflow`:在每个 `v*` 标签上,它会在固定环境中构建每个合约,将 WASM + SHA-256 作为 GitHub release 发布,在 stellar.expert 注册构建,并将 [SLSA](https://slsa.dev) 构建证明附加到 Rekor 透明度日志中。
- **从第一天起就在主网上获得验证** — 审计后的主网部署直接从 release artifact 裁剪而来,因此其链上哈希与注册的构建相匹配,并且 stellar.expert 显示绿色的 *verified* 徽章,并链接回此存储库。
## 为什么这很新颖
Nulth 使用 ZK 证明作为**唯一**的授权机制 —— 证明*就是*账户的签名,在 `__check_auth` 中进行验证。我们还没有发现另一个 Stellar 账户用证明本身代替支出签名;其他人将 ZK 放在了别处:
- 对比 **隐私池**(Moonlight, Nethermind)—— 隐藏*金额*,规则公开;Nulth 隐藏*规则*,金额公开。字面上的完全相反。
- 对比 **zk-voting / zkKYC** —— 资格/身份披露,而非支出授权。
- 对比 **passkey 智能钱包** —— 同样的 `__check_auth` 槽位,签名而非证明。
- 对比 **多签策略账户**(MultiClique)—— 链上策略字节,零 ZK。
不是代币池 —— 资金保持为标准 USDC;*授权*是隐私的。
## 我们从 RouteDock 中学到了什么
RouteDock 反馈:*“令人印象深刻……有用的智能账户……在合约上进行更实质性的测试。”*
Nulth 让智能账户成为主角,ZK 从第一个字节开始就承载核心逻辑,对抗性测试套件成为头条新闻 —— 而不是事后补充。每个 `AccError` 都是经过测试的阴性对照。每次链上拒绝都有一个交易哈希。评委要求测试;我们用 34 个 cargo + 7 个电路 + 5 个 e2e 驱动程序 = 总共 46 个测试作为回应,每个测试都将攻击映射到其错误代码再到其链上证据。
## 架构
```
OFF-CHAIN (operator / agent) ON-CHAIN (Soroban)
───────────────────────────── ──────────────────
policy = { cap, allowlist[], salt } Nulth account (DEPTH-16, BN254)
storage: vk, policy_commitment,
per payment (amount, dest): allowlist_root, token,
1. Web Worker: snarkjs.fullProve admin, frozen
~970 ms, DEPTH-16, in-browser __check_auth(payload, ProofSig, ctxs):
public: [amount, dest, commitment, 1. frozen? → AccountFrozen
root, sigpayload_hi/lo] 2. pub_signals[2,3] == stored?
2. proof = the "signature" on 3. sigpayload binding
token.transfer(from=account,…) 4. exactly one context?
3. fee-payer relays tx (pays XLM; 5. fn_name == "transfer"?
cannot authorize a spend) 6. token == pinned USDC?
7. from == self?
8. 0 < amount < 2¹⁰⁰?
9. amount/dest match signals?
10. Groth16 verify (native BN254)
11. → Ok → USDC transfer executes
```
**成本框** (DEPTH-16,USDC 路径,解码链上数据):
| | |
|---|---|
| 验证指令 | **34,149,591** |
| 400M 上限的百分比 | **8.537%** |
| 浏览器内证明时间 | **~970 毫秒** (Web Worker,DEPTH-16,M 系列 Mac) |
| 策略电路 | DEPTH-16 · 9,402 约束 · 65,536 个白名单插槽 |
| 披露电路 | 824 约束 · 173 毫秒浏览器证明 |
| 可信设置 | Hermez ptau phase-1 (公开,多方) + 单一本地 phase-2 (**开发设置** — 生产环境需要多方 phase-2) |
**信任边界** — 精确陈述:
拥有完整 mempool + vk + 链状态的观察者无法确定上限或任何未行使的白名单成员。他们只能知道实际支付的对手方以及上限的下限。
管理员密钥是完整的治理信任根:它不能一步完成支出(每次支出都需要已提交策略的有效证明),但它可以将已提交的策略轮换为它控制的策略然后再支出 —— 两个可观察的、触发事件的链上步骤。强化路径:多签 + 时间锁(已记录,尚未构建)。参见 [SECURITY.md](./SECURITY.md)。
## 下一步:合规级别
**Tier-1 ZK 审计员披露(已交付):** `cap ≤ regulatory_max` — 往来银行验证金库机器人的支出策略是否保持在 AML 限制内,而无需看到上限。真实的 ZK 证明,173 毫秒浏览器证明,在链上以 28,467,320 条指令完成验证。
**Tier-2 白名单 ⊆ 权威审查集 (Step-4 recon):** Merkle 集合上的子集包含关系 — 这是一个更难的问题。如果可行则使用真实的 ZK;无论情况如何,Tier-1 都会发布。
**运行累计预算:** 跨支付的并发强制执行是一个分布式系统问题,而不是密码学问题 — 共享状态上的并发证明需要排序保证,而当前的设计故意避免这一点。
## 文档
| 文件 | 内容 |
|---|---|
| [ADVERSARIAL_TESTING.md](./ADVERSARIAL_TESTING.md) | “我们如何破坏 Nulth” — 完整的错误代码矩阵 + 链上交易哈希 |
| [SECURITY.md](./SECURITY.md) | **权威威胁模型** — 对手、信任根、隐私边界、加密假设、披露 |
| [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) | 系统架构、`__check_auth` 门控顺序 + 错误代码、数据流、成本解码 |
| [docs/PROTOCOL.md](./docs/PROTOCOL.md) | ZK 授权原语、拟议标准、`ProofSig` 格式、披露扩展 |
| [docs/CIRCUIT_VERIFICATION.md](./docs/CIRCUIT_VERIFICATION.md) | 电路规范、可信设置溯源、可复现的黄金向量 |
| [REPORT_P1.md](./docs/reports/REPORT_P1.md) | 生产环境强化证据:16 个错误代码、重放已关闭 |
| [REPORT_GOVERNANCE.md](./docs/reports/REPORT_GOVERNANCE.md) | P2:rotate_policy、freeze/unfreeze、治理测试 |
| [REPORT_AGENT_DECK.md](./docs/reports/REPORT_AGENT_DECK.md) | Agent 越狱 + 利用演示 — 5 个真实的链上攻击回执 |
| [REPORT_VERIFY_TIER1.md](./docs/reports/REPORT_VERIFY_TIER1.md) | Tier-1 ZK 披露:电路、链上验证、浏览器演示 |
## 致谢
`stellar/soroban-examples` groth16_verifier · James Bachini 的 circom-on-Stellar 教程 · Hermez ptau · circomlib · circomlibjs。
## 许可证
MIT
标签:AI工具, Rust, Stellar, Web3, 加密货币, 区块链隐私, 可视化界面, 智能合约, 暗色界面, 网络流量审计, 自定义脚本, 零知识证明