值得信赖的区块链资讯!
零知识证明 – zkEVM源代码分析(State Circuit)
zkEVM是零知识证明相对复杂的零知识证明应用,源代码值得反复阅读和学习。
https://github.com/appliedzkp/zkevm-circuits.git
本文中采用的源代码对应的最后一个提交信息如下:
commit 1ec38f207f150733a90081d3825b4de9c3a0a724 (HEAD -> main)
Author: z2trillion <[email protected]>
Date: Thu Mar 24 15:42:09 2022 -0400
前一篇文章介绍了zkEVM的EVM Circuit的电路实现细节,接下来继续介绍State Circuit。
零知识证明 – zkEVM源代码分析(EVM Circuit)
State Circuit Configure
State电路实现了Stack,Memory以及Storage的检查。State电路实现在zkevm-circuits/src/state_circuit/state.rs。
pub struct StateCircuit<
F: FieldExt,
const SANITY_CHECK: bool,
const RW_COUNTER_MAX: usize,
const MEMORY_ADDRESS_MAX: usize,
const STACK_ADDRESS_MAX: usize,
const ROWS_MAX: usize,
> {
/// randomness used in linear combination
pub randomness: F,
/// witness for rw map
pub rw_map: RwMap,
}
StateCircuit的configure逻辑由Config的configure函数实现。
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
Config::configure(meta)
}
StateCircuit的大体电路结构如下图:
先着重介绍一下keys,占用了5个column,表示Memory,Stack以及Storage的key信息。State Circuit约束大部分都是围绕key-value的约束。为了兼容Memory,Stack以及Storage的Key信息,采用如下的5个Column。
keys[0] – tag
keys[1] – reserved
keys[2] – account address(memory/stack: 0)
keys[3] – address
keys[4] – storage key(memory/stack: 0)
其中key2,key4是给Storage用的。
Storage约束的信息还不够完整。Memory和Stack的约束逻辑类似。这篇文章详细介绍一下Stack的约束实现。在了解约束之前,先介绍Memory/Stack/Storage的信息组织形式:
| key0(tag) | key1 | key2 | key3(address) | key4 | read/write | rw counter | value |
|---|---|---|---|---|---|---|---|
| MEM | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| MEM | 0 | 0 | 0 | 0 | 0 | 2 | 0 |
| STACK | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| STACK | 0 | 0 | 0 | 0 | 0 | 2 | 0 |
所有的witness信息,按照key3(address)排序(按照地址顺序)。针对同一个地址的读写根据rw counter进行排序。
Tag分类
Tag类型包括了Memory,Stack以及Storage。针对不同的类型,采用不同的约束方式。
let q_tag_is = |meta: &mut VirtualCells<F>, tag_value: usize| {
let tag_cur = meta.query_advice(tag, Rotation::cur());
let all_possible_values = EMPTY_TAG..=STORAGE_TAG;
generate_lagrange_base_polynomial(tag_cur, tag_value, all_possible_values)
};
let q_memory = |meta: &mut VirtualCells<F>| q_tag_is(meta, MEMORY_TAG);
let q_stack = |meta: &mut VirtualCells<F>| q_tag_is(meta, STACK_TAG);
let q_storage = |meta: &mut VirtualCells<F>| q_tag_is(meta, STORAGE_TAG);
q_tag_is是拉格朗日多项式,针对某种Tag输出为1,其他Tag输出为0。q_memory/q_stack/q_storage就分别是这三种多项式。
Key关系判定
在约束电路中需要两种两种Key关系的判定:
1/ 前后的key是否一样
let key_is_same_with_prev: [IsZeroConfig<F>; 5] = [0, 1, 2, 3, 4].map(|idx| {
IsZeroChip::configure(
meta,
|meta| meta.query_fixed(s_enable, Rotation::cur()),
|meta| {
let value_cur = meta.query_advice(keys[idx], Rotation::cur());
let value_prev = meta.query_advice(keys[idx], Rotation::prev());
value_cur - value_prev
},
keys_diff_inv[idx],
)
});
2/ 是否key是一样
let q_all_keys_same = |_meta: &mut VirtualCells<F>| {
key_is_same_with_prev[0].is_zero_expression.clone()
* key_is_same_with_prev[1].is_zero_expression.clone()
* key_is_same_with_prev[2].is_zero_expression.clone()
* key_is_same_with_prev[3].is_zero_expression.clone()
* key_is_same_with_prev[4].is_zero_expression.clone()
};
let q_not_all_keys_same = |meta: &mut VirtualCells<F>| one.clone() - q_all_keys_same(meta);
通用约束
无论是Memory/Stack,还是Storage,有一些通用的约束:
1/ is_write必须是布尔型
2/ 如果是对同一个“地址”进行读操作,则读的数据必须和前一行的数据相同。前一行数据要不是同一地址的读,要不就是同一地址的写。
cb.require_boolean("is_write should be boolean", is_write);
cb.require_zero(
"if read and keys are same, value should be same with prev",
q_all_keys_same(meta) * is_read * (value_cur - value_prev),
);
cb.gate(s_enable)
RWC约束
对一个地址的读写操作,RW计数器是增长的。所谓的增长就是(rw_counter – rw_counter_prev -1) > 0。大于零的判定就是通过lookup。
meta.lookup_any("rw counter monotonicity", |meta| {
let s_enable = meta.query_fixed(s_enable, Rotation::cur());
let rw_counter_table = meta.query_fixed(rw_counter_table, Rotation::cur());
let rw_counter_prev = meta.query_advice(rw_counter, Rotation::prev());
let rw_counter = meta.query_advice(rw_counter, Rotation::cur());
vec![(
s_enable * q_all_keys_same(meta)
* (rw_counter - rw_counter_prev - one.clone()), /*
* - 1 because it needs to
* be strictly monotone */
rw_counter_table,
)]
});
Stack约束
在Stack的访问地址发生变化时,第一个操作必须是写操作。
meta.create_gate("Stack operation", |meta| {
let mut cb = new_cb();
let s_enable = meta.query_fixed(s_enable, Rotation::cur());
let is_write = meta.query_advice(is_write, Rotation::cur());
let q_read = one.clone() - is_write;
let key2 = meta.query_advice(keys[2], Rotation::cur());
let key4 = meta.query_advice(keys[4], Rotation::cur());
cb.require_zero("key2 is 0", key2);
cb.require_zero("key4 is 0", key4);
cb.require_zero(
"if address changes, operation is always a write",
q_not_all_keys_same(meta) * q_read,
);
cb.gate(s_enable * q_stack(meta))
});
Stack地址必须在一定的范围内,并且Stack Pointer的差距不能超过1。
meta.lookup_any("Stack address in allowed range", |meta| {
let q_stack = q_stack(meta);
let address_cur = meta.query_advice(address, Rotation::cur());
let stack_address_table_zero =
meta.query_fixed(stack_address_table_zero, Rotation::cur());
vec![(q_stack * address_cur, stack_address_table_zero)]
});
meta.create_gate("Stack pointer diff be 0 or 1", |meta| {
let mut cb = new_cb();
let s_enable = meta.query_fixed(s_enable, Rotation::cur());
let q_stack = q_stack(meta);
let tag_is_same_with_prev = key_is_same_with_prev[0].is_zero_expression.clone();
let call_id_same_with_prev = key_is_same_with_prev[1].is_zero_expression.clone();
let stack_ptr = meta.query_advice(keys[3], Rotation::cur());
let stack_ptr_prev = meta.query_advice(keys[3], Rotation::prev());
cb.require_boolean(
"stack pointer only increases by 0 or 1",
stack_ptr - stack_ptr_prev,
);
cb.gate(s_enable * q_stack * tag_is_same_with_prev * call_id_same_with_prev)
});
至此,Stack的相关约束就完成了。再看看assign的逻辑实现。
State Circuit Assign
所有的witness信息都存储在rw_map变量中。在过滤出"Memory/Stack/AccountStorage"信息后,按照key,rw_counter的顺序进行排序。针对每个row的信息,通过assign_row函数设置所有row信息。
layouter.assign_region(
|| "State operations",
|mut region| {
// TODO: a "START_TAG" row should be inserted before all other rows in the final
// implmentation. Here we start from 1 to prevent some
// col.prev() problems since blinding rows are unavailable for constaints.
let mut offset = 1;
let mut rows: Vec<RwRow<F>> = [
RwTableTag::Memory,
RwTableTag::Stack,
RwTableTag::AccountStorage,
]
.iter()
.map(|tag| {
rw_map.0[tag]
.iter()
.map(|rw| rw.table_assignment(randomness))
})
.flatten()
.collect();
rows.sort_by_key(|rw| (rw.tag, rw.key1, rw.key2, rw.key3, rw.key4, rw.rw_counter));
if rows.len() >= ROWS_MAX {
panic!("too many storage operations");
}
for (index, row) in rows.iter().enumerate() {
let row_prev = if index == 0 {
RwRow::default()
} else {
rows[index - 1]
};
self.assign_row(
&mut region,
offset,
*row,
row_prev,
&key_is_same_with_prev_chips,
)?;
offset += 1;
}
Ok(())
},
)
EVM/State Circuit证明了什么?
EVM/State Circuit证明了一些指令的正确逻辑执行,并且Memory/Stack的读写访问合理正确。
zkEVM除了这两部分电路外,还有一些外延的东西没有证明:1/ 执行程序的一致性 2/ Storage状态的正确性。这些后面再接着聊。
比推快讯
更多 >>- 土库曼斯坦合法化加密货币挖矿及交易,仍禁止将其作为支付手段
- 数据:ETH 流入 Binance 量创下 7 月以来最高记录,或反映巨鲸正预备抛售
- 数据,福布斯:比特币 2026 年价格预测集中在 12-17 万美元,机构资本部署成关键变量
- Flow 网络停机导致 NFT 借贷发生违约,Flowty 已暂停贷款结算
- 分析:USDC/USDT 溢价指数与市场流动性指标形成共振,短期内或将出现反弹
- 沉寂超 12 个月某实体解除 63 万枚 HYPE 质押,价值 2030 万美元
- 伊朗:接受使用加密货币支付先进武器订单
- Vitalik Buterin:以太坊使命是构建世界计算机并作为互联网核心基础设施
- Semantic 42 上线 Polymarket AI 竞技场新功能:普通用户也能一键部署 AI Agent 跟单/反向交易
- PeckShield:12 月重大加密安全事件造成约 7600 万美元损失,较上月下降 60%
- 数据:过去 24h Binance 净流出 3.21 亿 USDT
- BNB Chain 年度报告:独立地址总数突破 7 亿,日均交易量攀升至 1078 万笔
- 比特币 2025 年 Q4 回报率 -23.07% 创历史第二差表现,以太坊为 -28.28%
- 数据:116.22 枚 BTC 从匿名地址转出,经中转后流入 Coinbase
- 孙宇晨向 LLP 存入约 2 亿美金并提取 3800 万美金买入 1325 万枚 LIT
- 分析师:比特币 10 周和 50 周移动均线再次交叉,若历史重演或将出现深度回调
- Binance 将下架 BTC/RON 现货交易对,RON 为法币
- 投资银行 The Benchmark Company 重申对 MSTR 的买入评级
- 比特币提币情绪延续,过去 24 小时 CEX 净流出 3,347.33 枚 BTC
- Opinion:由于预言机受污染导致 Metamask 市场结果偏差,将进行全额赔偿
- a16z crypto 发布 2026 年加密行业 17 条趋势展望
- 数据:监测到 6,323.64 万 USDT 转入 Binance
- 数据:过去 24 小时全网爆仓 2.33 亿美元,多单爆仓 1.55 亿美元,空单爆仓 7,819.93 万美元
- 分析:2025 年以太坊“牺牲”超 1 亿美元补贴生态扩张
- 英国等 40 多国实施新加密税务规则,要求交易所收集用户交易记录并报告
- 报告:2025 年加密亿万富豪成最大输家之一
- 某地址向 Hyperliquid 充值 800 万美元保证金并做多 1376 万美元多币种头寸
- 数据:Wintermute 向 Binance 转移 720 万 USDT,价值 720 万美元
- 观点:比特币在减半后一年首次录得下跌,四年周期或被打破
- 昨日美国比特币现货 ETF 净流出 3.481 亿美元
- 数据:成本 400 美元以下 ETH 远古巨鲸多次获利出逃,此后币价常阶段性见顶
- Bithumb 将上线 XAUT 韩元交易对
- 张铮文:短期争议终将过去,专注于 Neo 持续建设和长期发展
- Neo 联创张铮文公布治理架构与账目情况并宣布回归主网管理
- 某巨鲸持有 PUMP 六个月疑似认亏清仓,浮亏 153 万美元
- 全球最大黄金和白银 ETF 开始减仓,分别较上日减少 1.43 吨和 11.28 吨
- 数据,美国 XRP 现货 ETF 单日总净流入 558 万美元
- 多家国有大行公告:数字人民币计结息规则与活期存款一致
- 数据:TLM 24 小时跌超 42%,LUNA 跌超 14%
- Peter Schiff:Strategy 购买比特币的策略摧毁了股东价值
- 黄金 2025 全年涨约 65%并创下逾 50 次新高,白银涨约 150%
- Gate 研究院:期权市场低波动蓄势,资金布局偏向看涨价差结构
- RootData:STABLE 将于一周后解锁价值约 1247 万美元的代币
- UniSat:Runes 索引出现问题,将暂停更新数据
- Upbit 暂停 NKN 网络数字资产充值与提现
- Glassnode:现货 ETF 资金流暂未显现新的需求迹象
- 数据:Hyperliquid 平台鲸鱼当前持仓 55.6 亿美元,多空持仓比为 0.93
- 加密恐慌指数降至 20,极度恐慌状态进一步加剧
- Delphi Digital:比特币或将迎来流动性拐点,黄金完成宽松周期内的重新定价
- 针对马克·库班和达拉斯独行侠队的加密货币集体诉讼被驳回
比推专栏
更多 >>观点
比推热门文章
- 土库曼斯坦合法化加密货币挖矿及交易,仍禁止将其作为支付手段
- 数据:ETH 流入 Binance 量创下 7 月以来最高记录,或反映巨鲸正预备抛售
- 数据,福布斯:比特币 2026 年价格预测集中在 12-17 万美元,机构资本部署成关键变量
- Flow 网络停机导致 NFT 借贷发生违约,Flowty 已暂停贷款结算
- 分析:USDC/USDT 溢价指数与市场流动性指标形成共振,短期内或将出现反弹
- 沉寂超 12 个月某实体解除 63 万枚 HYPE 质押,价值 2030 万美元
- 伊朗:接受使用加密货币支付先进武器订单
- Vitalik Buterin:以太坊使命是构建世界计算机并作为互联网核心基础设施
- Semantic 42 上线 Polymarket AI 竞技场新功能:普通用户也能一键部署 AI Agent 跟单/反向交易
- PeckShield:12 月重大加密安全事件造成约 7600 万美元损失,较上月下降 60%
比推 APP



