achronyme/achronyme
GitHub: achronyme/achronyme
一门支持双执行模式的零知识电路编程语言,可用同一份代码进行通用执行和 ZK 电路编译,内置证明生成与 Solidity 合约导出。
Stars: 5 | Forks: 0
# 缩写
[](https://github.com/achronyme/achronyme/actions/workflows/ci.yml)
[](https://github.com/achronyme/achronyme/actions/workflows/docs.yml)
一种用于零知识电路的编程语言。
编写可读的代码。决定证明的内容。通用执行和 ZK 电路编译使用同一种语言。
## 安装
```
curl -fsSL https://achrony.me/install.sh | sh
```
这会将 `ach` 二进制文件安装到 `~/.local/bin`。需要 Linux 或 macOS(x86_64 或 aarch64)。
### 从源码构建
```
git clone https://github.com/achronyme/achronyme.git
cd achronyme
cargo build --release
cargo test --workspace # 2,000+ unit tests
bash test/run_tests.sh # 150+ integration tests
```
## 快速预览
### 通用执行
```
let make_counter = fn(init) {
mut n = init
return fn() { n = n + 1; return n }
}
let c = make_counter(0)
print(c()) // 1
print(c()) // 2
```
### ZK 电路
```
public root
witness leaf
witness path[3]
witness indices[3]
merkle_verify(root, leaf, path, indices)
```
```
ach circuit merkle.ach --inputs "root=...,leaf=42,path_0=...,path_1=...,path_2=...,indices_0=0,indices_1=1,indices_2=0"
# → circuit.r1cs + witness.wtns (兼容 snarkjs)
```
### 内联证明生成
```
let secret = 0p42
let hash = 0p17159... // poseidon(42, 0)
let p = prove {
witness secret
public hash
assert_eq(poseidon(secret, 0), hash)
}
print(proof_json(p)) // Groth16 proof, verifiable on-chain
```
## 工作原理
Achronyme 从同一源码支持两种执行模式:
**VM 模式** (`ach run`) —— 完整语言:闭包、递归、GC、数组、map、字符串、I/O。代码像任何脚本语言一样运行。
**电路模式** (`ach circuit`) —— 编译为 BN254 上的算术约束。运行时无循环,无 I/O —— 一切都被展开并扁平化为用于零知识证明的约束系统。
`prove {}` 块连接两者:它在 VM 内运行,将其主体编译为电路,从捕获的变量生成 witness,并产生加密证明 —— 所有这些都在一个表达式中完成。
```
Source (.ach)
│
├─► Parser (Pratt) → AST
│ │
│ ├─► Bytecode → VM (run mode)
│ │
│ └─► SSA IR → Optimize
│ │
│ ┌───┴───┐
│ ▼ ▼
│ R1CS Plonkish
│ (Groth16) (KZG-PlonK)
│ │ │
│ ▼ ▼
│ .r1cs Gates/Lookups
│ .wtns Copy constraints
│ │ │
│ └───┬───┘
│ ▼
│ Native proof
│
└─► prove { } → compile + witness + verify + proof (inline)
```
## 语言
### 类型
| Type | Examples |
|------|---------|
| Int | `42`, `-7` |
| Bool | `true`, `false` |
| String | `"hello"` |
| List | `[1, 2, 3]` |
| Map | `{"a": 1, "b": 2}` |
| Field | `0p42`, `0pxFF`, `0pb1010` |
| BigInt256 | `0i256xFF`, `0i256d42` |
| BigInt512 | `0i512xFF`, `0i512d100` |
| Function | `fn(x) { x + 1 }` |
| Proof | result of `prove { }` |
| Nil | `nil` |
### 控制流
```
if x > 0 { print("positive") } else { print("non-positive") }
while n > 0 { n = n - 1 }
for item in list { print(item) }
for i in 0..10 { print(i) }
```
### 函数与闭包
```
let add = fn(a, b) { a + b }
let fib = fn fib(n) {
if n < 2 { return n }
return fib(n - 1) + fib(n - 2)
}
// Closures capture environment
let make_adder = fn(x) { fn(y) { x + y } }
let add5 = make_adder(5)
print(add5(3)) // 8
```
### 域元素
BN254 标量域。内部为 Montgomery 形式。使用 `0p` 前缀创建:
```
let a = 0p42
let b = 0pxFF
let c = 0pb1010
let sum = a + b
let prod = a * b
let inv = 0p1 / a
```
### BigInt(仅限 VM)
用于加密操作的固定宽度无符号整数(256 位和 512 位):
```
let a = 0i256xFF
let b = bigint256(42)
let bits = a.to_bits()
let masked = a.bit_and(b)
```
## 电路特性
### 声明
```
public output // public input (instance)
witness secret // private input (witness)
witness arr[4] // witness array (arr_0, arr_1, arr_2, arr_3)
```
### 内置函数
| Builtin | Description | R1CS cost | Plonkish cost |
|---------|-------------|-----------|---------------|
| `assert_eq(a, b)` | 强制相等 | 1 | 1 |
| `assert(expr)` | 强制布尔值为真 | 2 | 2 |
| `poseidon(a, b)` | Poseidon 2 对 1 哈希 | 361 | 361 |
| `poseidon_many(a, b, c, ...)` | 左折叠 Poseidon | 361*(n-1) | 361*(n-1) |
| `mux(cond, a, b)` | 条件选择 | 2 | 1 |
| `range_check(x, bits)` | 值适合 N 位 | bits+1 | 1 (lookup) |
| `merkle_verify(root, leaf, path, indices)` | Merkle 成员证明 | ~1090/level | ~1090/level |
| `len(arr)` | 编译时数组长度 | 0 | 0 |
### 电路中的运算符
| Operation | R1CS | Plonkish |
|-----------|------|----------|
| `+`, `-` | 0 | 0 |
| `*` | 1 | 1 |
| `/` | 2 | 2 |
| `^` (constant exp) | O(log n) | O(log n) |
| `==`, `!=` | 2 | 2 |
| `<`, `<=`, `>`, `>=` | ~760 | ~760 |
| `&&`, `\|\|` | 3 | 3 |
| `!` | 1 | 1 |
### 电路中的函数
函数在每个调用点内联。无动态分发,无递归。
```
witness a, b
public out
fn hash_pair(x, y) { poseidon(x, y) }
assert_eq(hash_pair(a, b), out)
```
### 电路中的控制流
`if/else` 编译为 `mux`(两个分支都会被求值)。`for` 循环静态展开。`while`、`break`、`continue` 会在编译时被拒绝。
```
witness vals[4]
public total
let sum = vals[0]
let sum = sum + vals[1]
let sum = sum + vals[2]
let sum = sum + vals[3]
assert_eq(sum, total)
```
## CLI
```
# 运行程序
ach run script.ach
# 使用 PlonK prove 后端运行
ach run script.ach --prove-backend plonkish
# 编译 circuit (源码内声明)
ach circuit circuit.ach --inputs "x=42,y=7"
# 编译 circuit (CLI 声明)
ach circuit circuit.ach --public "out" --witness "a,b" --inputs "out=42,a=6,b=7"
# Plonkish 后端
ach circuit circuit.ach --backend plonkish --inputs "x=42,y=7"
# 生成 Plonkish 证明
ach circuit circuit.ach --backend plonkish --inputs "x=42" --prove
# 生成 Solidity verifier 合约
ach circuit circuit.ach --inputs "x=42,y=7" --solidity
# 编译为 bytecode
ach compile script.ach --output script.achb
# 反汇编
ach disassemble script.ach
```
输出的 `.r1cs` 和 `.wtns` 文件与 snarkjs 兼容:
```
snarkjs groth16 setup circuit.r1cs pot12_final.ptau circuit.zkey
snarkjs groth16 prove circuit.zkey witness.wtns proof.json public.json
snarkjs groth16 verify verification_key.json public.json proof.json
```
## 证明块
`prove {}` 编译电路,从封闭作用域捕获变量,生成 witness,并返回证明 —— 全部内联完成。
```
let a = 0p6
let b = 0p7
let product = 0p42
let p = prove {
witness a
witness b
public product
assert_eq(a * b, product)
}
```
`public`/`witness` 声明中的变量名必须与外部作用域中的 `let` 绑定匹配。整数值会自动提升为域元素。
结果是一个 `Proof` 对象(根据 `--prove-backend` 是 Groth16 或 PlonK)。使用 `proof_json(p)`、`proof_public(p)`、`proof_vkey(p)` 提取组件。使用 `verify_proof(p)` 进行验证。
如果没有可用的证明后端,该块仍会编译电路、生成 witness 并在本地验证约束(返回 `nil`)。
## 优化遍
SSA IR 在生成约束之前运行四遍优化:
- **常量折叠** —— 在编译时计算已知常量的算术运算
- **死代码消除** —— 移除未使用的指令
- **布尔传播** —— 跟踪已证明的布尔变量,跳过冗余强制
- **污点分析** —— 警告约束不足或未使用的输入
使用 `--no-optimize` 禁用。
## 项目结构
```
achronyme/
├── achronyme-parser/ Hand-written Pratt lexer + recursive descent parser
├── ir/ SSA intermediate representation, optimization passes
├── compiler/ Bytecode compiler, R1CS backend, Plonkish backend
├── vm/ Register-based VM (37 opcodes, prototype method dispatch)
├── memory/ Heap, GC, FieldElement (BN254 Montgomery), BigInt
├── constraints/ R1CS/Plonkish systems, Poseidon hash, binary export
├── cli/ CLI, native Groth16 (ark-groth16) & PlonK (halo2-KZG)
├── std/ Standard library (NativeModule: parse_int, join, I/O)
├── ach-macros/ Proc-macros: #[ach_native], #[ach_module]
├── docs/ Documentation site (Astro + Starlight, 83 pages, EN/ES)
└── test/
├── vm/ VM/interpreter integration tests
├── circuit/ Circuit compilation tests
├── prove/ Prove block tests
└── run_tests.sh Integration test runner (158 tests)
```
## 全局函数
无需导入即可使用 16 个全局函数。大多数操作现在使用[方法语法](#methods)。
| Function | Arity | Description |
|----------|-------|-------------|
| `print(...)` | variadic | 打印值到 stdout |
| `typeof(x)` | 1 | 类型名称作为 String |
| `assert(x)` | 1 | 运行时断言 |
| `time()` | 0 | Unix 时间戳 |
| `gc_stats()` | 0 | GC 统计信息作为 map |
| `poseidon(a, b)` | 2 | Poseidon 2 对 1 哈希 (BN254) |
| `poseidon_many(a, b, ...)` | variadic | 左折叠 Poseidon 哈希 |
| `verify_proof(p)` | 1 | 验证 Groth16 证明 |
| `proof_json(p)` | 1 | 提取证明 JSON |
| `proof_public(p)` | 1 | 提取公开输入 JSON |
| `proof_vkey(p)` | 1 | 提取验证密钥 JSON |
| `bigint256(x)` | 1 | 构造 256 位无符号整数 |
| `bigint512(x)` | 1 | 构造 512 位无符号整数 |
| `from_bits(bits, width)` | 2 | 位列表转 BigInt |
| `parse_int(str)` | 1 | 解析字符串为整数 |
| `join(list, sep)` | 2 | 用分隔符连接字符串 |
## 方法
值具有使用点语法调用的特定类型方法:`value.method(args)`。
```
// String methods
let upper = "hello".to_upper() // "HELLO"
let words = "a,b,c".split(",") // ["a", "b", "c"]
// List methods
let doubled = [1, 2, 3].map(fn(n) { n * 2 }) // [2, 4, 6]
let evens = [1, 2, 3, 4].filter(fn(n) { n % 2 == 0 }) // [2, 4]
// Map methods
let m = {name: "Alice", age: 30}
assert(m.contains_key("name"))
m.set("city", "NYC")
// Int methods
assert((-42).abs() == 42)
assert(2.pow(10) == 1024)
```
跨 6 种类型的 **50 个方法**:Int (6)、String (14)、List (13)、Map (8)、Field (2)、BigInt (7)。
**静态命名空间** 提供类型级常量:`Int::MAX`、`Int::MIN`、`Field::ZERO`、`Field::ONE`、`Field::ORDER`、`BigInt::from_bits`。
## 状态
- 2,125+ 单元测试 + 158 集成测试
- 与 snarkjs 交叉验证(独立约束验证)
- 2 个 ZK 后端:R1CS/Groth16 + Plonkish/KZG-PlonK
- 原生进程内证明生成(无需外部工具)
- 兼容 snarkjs 的二进制导出
- Solidity 验证合约生成
- Poseidon 哈希兼容 circomlibjs
- 带源代码行号的运行时错误
- [文档](https://docs.achrony.me)
## 许可证
GPL-3.0
标签:Android, BN254, DSL, Groth16, R1CS, Rust, Web3, ZKP, zkSNARKs, 全同态加密, 区块链开发, 去中心化, 可视化界面, 密码学, 手动系统调用, 智能合约, 生成式AI安全, 电路编译, 编程语言, 编译器, 网络流量审计, 虚拟机, 通知系统, 隐私计算, 零知识证明, 默克尔树