Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
zkevm-circuits
zkevm-circuits
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 0
    • Merge Requests 0
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Package Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar

新注册的用户请输入邮箱并保存,随后登录邮箱激活账号。后续可直接使用邮箱登录!

  • zkp
  • zkevm-circuitszkevm-circuits
  • Wiki
    • Basics
  • halo2

halo2 · Changes

Page history
restyle docs authored Aug 06, 2024 by geruiwang's avatar geruiwang
Show whitespace changes
Inline Side-by-side
Showing with 1 addition and 1 deletion
+1 -1
  • basics/halo2.markdown basics/halo2.markdown +1 -1
  • No files found.
basics/halo2.markdown 0 → 100644
View page @ a8eeca49
# Halo2电路基础
如需继续往下学习,需要掌握和了解关于电路的基础知识和Rust的基本语法。相关资料可以参考:
- [PLONK Tutorials](https://learn.z2o-k7e.world/plonk-intro-cn/plonk-arithmetization.html) & [Lookup Gates @secbit](https://learn.z2o-k7e.world/plonk-intro-cn/plonk-lookup.html)
- [Rust 圣经](https://course.rs/about-book.html)
### 1. Lookup Gate
Lookup Gate的作用是证明一条(或多条)记录是否存在于一个公开的表中。这可能会有点像 Merkle Tree,如果我们把表格按行计算 hash,这些 hash 就可以产生一个 Merkle Root,然后通过 Merkle Path 就能证明一条记录是否存在表格中。但是这个方法(以及所有的 Vector Commitment 方案)存在以下两个缺点:
1. 证明时会暴露记录在表格中的位置。
2. 所产生的证明即 Merkle Path,可能会比较大,最坏情况是 *O*(*d*log*n*)。
为了解决这些问题,在电路中实现lookup,Halo2给出了[Halo2-lookup 方案](https://learn.z2o-k7e.world/plonk-intro-cn/plonk-lookup.html#halo2-lookup-方案)。在此我们只需要简单理解Lookup的相关概念,需要深入学习如何写一个简单的电路,可以查看参考资料。
### 2. Circuits 电路结构
为了能够看懂core中各个电路的名词和概念,在此我们补充一些电路结构的基础知识。
> [The halo2 Book](https://zcash.github.io/halo2/concepts/proofs.html): The language that we use to express circuits for a particular proof system is called an ***arithmetization***. Usually, an arithmetization will define circuits in terms of polynomial constraints on variables over a field. [2](https://learn.z2o-k7e.world/halo2/chap-0/index.html#9)
<img src="../../image/APIs_image_1.png" alt="img" style="zoom: 33%;" />
- 电路表整体由单元(`cell`)、列(`Column`)和行(`Row`)组成。
- 相邻的`cell`、`row` 和 `colum` 的任意组合可以构成 `region`。
- 列又可以分为三种类型:`advice`,`instance` 和 `selector`。
- **`advice columns`**:包含了 `private input` & 电路运行中所需的中间变量,即witness,这部分只有prover知道
- **`instance columns`**:包含了 Prover/Verifier 之间共享的输入,通常用于公共输入 (public inputs)
- **`selector columns`**/**`fixed columns`**:包含在 key generation 阶段设置的 preprocessed values,可以视为是电路结构固定的一部分,也是可以被 pre-compute 的。比如查找表 Lookup table column。
> Tips: 同一行可以支持若干种不同的约束, 比如三元三次, 或者三元二次, 可以通过 selector 来选择具体需要满足哪个约束。比如有 3 个 custom gate, 可以只满足其中一个就 OK , 或者满足其中的 2 个,非常灵活
### 3. 一个简单的示例
下面我们演示如何使用 Halo2 来实现一个基本的加法电路。实现电路一般按照以下三个流程进行:
#### 1). 确定电路配置
首先,确定电路需要的列数和类型。在我们的加法电路例子中,我们需要三列 `Advice` 列来存储输入 `a`、输入 `b` 和输出 `sum`。
我们定义一个结构来存储电路的输入 `a` 和 `b`。
```rust
#[derive(Clone)]
struct MyCircuit {
a: u64,
b: u64,
}
```
然后,在 `configure` 方法中,我们定义电路需要的 `Advice` 列。
```rust
impl Circuit<()> for MyCircuit {
type Config = (Column<Advice>, Column<Advice>, Column<Advice>);
type FloorPlanner = SimpleFloorPlanner;
fn configure(meta: &mut ConstraintSystem<()>) -> Self::Config {
let col_a = meta.advice_column();
let col_b = meta.advice_column();
let col_sum = meta.advice_column();
meta.enable_equality(col_a);
meta.enable_equality(col_b);
meta.enable_equality(col_sum);
(col_a, col_b, col_sum)
}
}
```
#### 2). 确定电路需要的门
接下来,确定电路需要的门。门可以是标准的乘法门、加法门,或者是自定义门。如果需要特定功能,可以添加 lookup 表。
在我们的例子中,只需要一个简单的加法约束,即 `sum = a + b`。
在 `configure` 方法中,我们还需要定义电路的约束。这包括定义一个加法门,确保 `sum = a + b`。
```rust
impl Circuit<()> for MyCircuit {
fn configure(meta: &mut ConstraintSystem<()>) -> Self::Config {
// ... 省略前面的代码
meta.create_gate("Addition", |meta| {
let a = meta.query_advice(col_a, Rotation::cur());
let b = meta.query_advice(col_b, Rotation::cur());
let sum = meta.query_advice(col_sum, Rotation::cur());
vec![sum - (a + b)]
});
(col_a, col_b, col_sum)
}
}
```
#### 3). 填充 witness
最后,根据电路所需的输入输出,填充 witness。witness 是电路计算过程中实际使用的值。假设我们电路的输入值 `a` 和 `b` 分别是 3 和 4,那么电路的 witness 就是:
- `a = 3`
- `b = 4`
- `sum = a + b = 7`
电路的 witness 可以用一个表格来表示,表格的每一行代表一个电路的列,每一列代表一个电路的行。对于这个简单的电路,我们只需要一个行来表示计算过程。
| | Column `a` | Column `b` | Column `sum` |
| ----- | ---------- | ---------- | ------------ |
| Row 0 | 3 | 4 | 7 |
在我们的例子中,我们将 `a`、`b` 和 `sum` 分配到对应的列中。
在 `synthesize` 方法中,我们使用 `Layouter` 将实际的值(witness)分配到电路的列中。
```rust
impl Circuit<()> for MyCircuit {
fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<()>) -> Result<(), Error> {
let (col_a, col_b, col_sum) = config;
layouter.assign_region(
|| "Assign values",
|mut region| {
region.assign_advice(|| "a", col_a, 0, || Ok(self.a.into()))?;
region.assign_advice(|| "b", col_b, 0, || Ok(self.b.into()))?;
region.assign_advice(|| "sum", col_sum, 0, || Ok((self.a + self.b).into()))?;
Ok(())
},
)
}
}
```
完整代码如下:
```rust
use halo2::circuit::{Layouter, SimpleFloorPlanner};
use halo2::plonk::{Advice, Circuit, Column, ConstraintSystem, Error};
use halo2::poly::Rotation;
#[derive(Clone)]
struct MyCircuit {
a: u64,
b: u64,
}
impl Circuit<()> for MyCircuit {
type Config = (Column<Advice>, Column<Advice>, Column<Advice>);
type FloorPlanner = SimpleFloorPlanner;
fn configure(meta: &mut ConstraintSystem<()>) -> Self::Config {
let col_a = meta.advice_column();
let col_b = meta.advice_column();
let col_sum = meta.advice_column();
meta.enable_equality(col_a);
meta.enable_equality(col_b);
meta.enable_equality(col_sum);
meta.create_gate("Addition", |meta| {
let a = meta.query_advice(col_a, Rotation::cur());
let b = meta.query_advice(col_b, Rotation::cur());
let sum = meta.query_advice(col_sum, Rotation::cur());
vec![sum - (a + b)]
});
(col_a, col_b, col_sum)
}
fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<()>) -> Result<(), Error> {
let (col_a, col_b, col_sum) = config;
layouter.assign_region(
|| "Assign values",
|mut region| {
region.assign_advice(|| "a", col_a, 0, || Ok(self.a.into()))?;
region.assign_advice(|| "b", col_b, 0, || Ok(self.b.into()))?;
region.assign_advice(|| "sum", col_sum, 0, || Ok((self.a + self.b).into()))?;
Ok(())
},
)
}
}
fn main() {
let circuit = MyCircuit { a: 3, b: 4 };
let prover = halo2::dev::MockProver::run(4, &circuit, vec![]).unwrap();
prover.assert_satisfied();
}
```
### 参考资料
1. [zcash halo2 book](https://zcash.github.io/halo2/) / [github](https://github.com/zcash/halo2/blob/main/book/)
2. [zcash halo2 book 中文翻译](https://trapdoor-tech.github.io/halo2-book-chinese/) / [github](https://trapdoor-tech.github.io/halo2-book-chinese/)
3. [Halo2 基础](https://learn.z2o-k7e.world/halo2/halo2.html)
4. [R1CS约束](https://tlu.tarilabs.com/cryptography/rank-1)
5. [zkevm的设计和挑战](https://learnblockchain.cn/article/3108)
6. [以太坊相关操作码集合](https://cypherpunks-core.github.io/ethereumbook/13evm.html)
Clone repository
  • basics
    • evm
    • halo2
  • code notes
    • binary_number_with_real_selector
    • how to use macro
    • simple_lt
    • simple_lt_word
  • Home
  • image
  • zkevm docs
    • 1 introduction
    • 10 public
    • 11 fixed
    • 12 exp
    • 13 keccak
    • 14 comparisons
    • 15 differences
View All Pages

Copyright © 2024 ChainWeaver Org. All Rights Reserved. 版权所有。

京ICP备2023035722号-3

京公网安备 11010802044225号