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
    • Zkevm docs
  • 6 bytecode

6 bytecode · Changes

Page history
feat: update docs --story=1019296 authored Aug 01, 2024 by chenxuanhui's avatar chenxuanhui
Hide whitespace changes
Inline Side-by-side
Showing with 139 additions and 55 deletions
+139 -55
  • zkevm-docs/6-bytecode.markdown zkevm-docs/6-bytecode.markdown +139 -55
  • No files found.
zkevm-docs/6-bytecode.markdown
View page @ 0812eb1d
Bytecode circuit用于约束合约的Bytecode,为其他电路提供bytecode的来源依据,其他子电路可通过Lookup约束来验证所操作bytecode码是否是合法的。
Bytecode电路用于约束智能合约的字节码,并为其他电路提供字节码的来源依据。通过Lookup约束,其他子电路可以验证操作的字节码是否合法。
Bytecode table中存放的可能并不只是一个合约的Bytecode,不同的合约的Bytecode以`address`进行标识,Bytecode与address是唯一一一对应。
对于一个合约的Bytecode而言,`pc`是opcode或者no_code(push的byte)唯一的标识
在Bytecode表中存放的可能不仅仅是一个合约的字节码,不同合约的字节码以地址(address)进行标识,每个地址唯一对应一个字节码。对于一个合约的字节码来说,`pc`是opcode或者no_code(push的byte)唯一的标识。
在对Bytecode进行处理时,将Bytecode分为两类:
1. Opcode(非PUSH):操作指令,如ADD、SUB、CODECOPY
2. Opcode(PUSH):PUSH1~PUSH32,以及PUSH的Byte
**Opcode(非PUSH)**:
- 操作指令,如ADD、SUB、CODECOPY等。
**Opcode(PUSH)**:
- 包括PUSH1至PUSH32,以及PUSH操作码后跟随的字节。
## Witness、Column设计
### Witness
### Witness设计
Witness结构体`Row`包含多个字段,用于记录字节码处理过程中的相关信息:
```rust
#[derive(Clone, Debug, Default, Serialize)]
......@@ -37,12 +42,17 @@ pub struct Row {
}
```
- cnt:如果是非PUSH的Opcode则cnt=0, 对于PUSH指令,cnt为PUSH的byte的数量,如PUSH1 --> cnt=1, PUSH2 --> cnt=2, PUSH31 --> cnt=31, PUSH32 --> cnt=32,对于no_code则cnt的值为(0~cnt-1)
- is_high:cnt >=16 ---> 1,cnt < 16 ---> 0,主要是用于辅助计算acc的值(规定acc的值最多为16个字节)
- acc_hi:cnt >=16的Bytecode执行此计算,`acc_hi_pre * 256 + bytecode`,即计算byte的累加值
- acc_lo:cnt < 16的Bytecode执行此计算,`acc_lo_pre * 256 + bytecode`,即计算byte的累加值
- value_hi:cnt >= 16的Bytecode的最终累加值,即最终的acc_hi
- value_lo:cnt < 15的Bytecode的最终累加值,即最终的acc_lo
- **cnt**: 如果是非 PUSH 的 Opcode 则 cnt=0,对于 PUSH 指令,cnt 为 PUSH 的 byte 的数量,如 PUSH1 --> cnt=1, PUSH2 --> cnt=2, PUSH31 --> cnt=31, PUSH32 --> cnt=32,对于 no_code 则 cnt 的值为 (0~cnt-1)。
- **is_high**: cnt >= 16 时为 1,cnt < 16 时为 0,主要用于辅助计算 acc 的值(规定 acc 的值最多为 16 个字节)。
- **acc_hi**: cnt >= 16 的 Bytecode 执行此计算,`acc_hi_pre * 256 + bytecode`,即计算 byte 的累加值。
- **acc_lo**: cnt < 16 的 Bytecode 执行此计算,`acc_lo_pre * 256 + bytecode`,即计算 byte 的累加值。
- **value_hi**: cnt >= 16 的 Bytecode 的最终累加值,即最终的 acc_hi。
- **value_lo**: cnt < 15 的 Bytecode 的最终累加值,即最终的 acc_lo。
注:Opcode(非PUSH)的 cnt、is_high、acc_hi、acc_lo、value_hi、value_lo值都为0
......@@ -54,7 +64,7 @@ PUSH18 0x02030405060708090a0b0c0d0e0f10111213
ADD
```
假如addr为0xaa,则表格如下(这里的Opcode以字符串的形式表现比较形象):
假设 addr 为 0xaa,则表格如下:
| addr | pc | bytecode | acc_hi | acc_lo | value_hi | value_lo | cnt | is_high |
| ---- | ---- | -------- | ------ | ------------------------------- | -------- | --------------------------------- | ---- | ------- |
......@@ -81,7 +91,9 @@ ADD
| 0xaa | 21 | ADD | 0x0 | 0x0 | 0x0 | 0x0 | 0 | 0 |
| 0xaa | 22 | STOP | 0x0 | 0x0 | 0x0 | 0x0 | 0 | 0 |
### Circuit Column
### Column设计
Bytecode电路的配置结构体`BytecodeCircuitConfig`包含多个列和选择器,用于约束和验证字节码:
```rust
#[derive(Clone)]
......@@ -131,83 +143,157 @@ pub struct BytecodeCircuitConfig<F> {
## 门约束
addr = 0 ----> Padding row(所有值都为0)
cnt=0的情况有三种:Opcode(非PUSH)、PUSH指令PUSH的最后一个byte、padding的row
cnt_prev=0 && cnt_cur !=0 ----> OPCODE(PUSH)
- **Padding行**:`addr = 0`
cnt_prev=0 && cnt_cur =0 && addr != 0 ---> OPCODE(非PUSH)
- **Opcode(PUSH)**:`cnt_prev=0 && cnt_cur !=0`
cnt_prev != 0 && cnt_cur != 0 ------> PUSH的byte(非push的最后一个字节)
- **Opcode(非PUSH)**:`cnt_prev=0 && cnt_cur =0 && addr != 0`
cnt_prev != 0 && cnt_cur == 0 -------> PUSH的最后一个字节
- **PUSH的byte**:`cnt_prev != 0 && cnt_cur != 0`
cnt=0的情况有三种:Opcode(非PUSH)、PUSH指令PUSH的最后一个byte、padding的row
- **PUSH的最后一个byte**:`cnt_prev != 0 && cnt_cur == 0`
#### **Pc 约束**
**Pc**
- 当地址发生变化时(表示新的合约开始),`pc` 应从 0 开始:
addr change ----> pc=0 (addr发生变化,说明是一个新的合约,pc应该从0开始)
```
addr change ----> pc = 0
```
addr unchange && addr != 0 ----> pc_cur - pc_prev = 1 (同一个合约中pc是累加的)
- 当地址未发生变化且地址不为 0 时(同一个合约中),`pc` 是累加的:
**Padding row**
```
addr unchange && addr != 0 ----> pc_cur - pc_prev = 1
```
cnt、addr、pc、bytecode、value_hi、value_lo、acc_hi、acc_lo、is_high, rlc_acc, hash_hi, hash_lo都为0
#### **Padding Row**
**Opcode(非PUSH)**
在填充行中,所有相关字段的值都为 0:
```
cnt、addr、pc、bytecode、value_hi、value_lo、acc_hi、acc_lo、is_high、rlc_acc、hash_hi、hash_lo 都为 0
```
cnt、value_hi、value_lo、acc_hi、acc_lo、is_high都为0
#### **Opcode(非 PUSH)**
**Opcode(PUSH)**
对于非 PUSH 的操作码,以下字段的值都为 0:
cnt !=0, acc_hi=0,acc_lo=0
```
cnt、value_hi、value_lo、acc_hi、acc_lo、is_high 都为 0
```
value_hi和value_lo由下一行进行约束,即当cnt_prev!=0时,value_hi、value_lo都和上一行相等,以此类推则PUSH指令的所有的row的value_hi和value_lo都会等于PUSH的最后一个byte的value_hi和value_lo(PUSH的最后一个byte的value_hi和value_lo是我们想要的最终的value_hi和value_lo)
#### **Opcode(PUSH)**
**cnt_prev != 0**
对于 PUSH 指令:
cnt_prev != 0说明当前行为PUSH指令PUSH的byte
- `cnt` 不为 0,`acc_hi` 和 `acc_lo` 均为 0:
cnt_prev !=0 ----> `cnt_prev - cnt_cur = 1 `(PUSH指令的cnt是递减的)
```
cnt != 0, acc_hi = 0, acc_lo = 0
```
cnt_prev !=0 -----> `is_high_prev - is_heigh_cur - cnt_is_15 = 0` (用于约束cnt=15和cat=16的分界线的cnt, 当cnt=15时, cnt_is_15=1,因为cnt>=16时is_high=1, cnt<16时is_high=0, 所以cnt_is_16_is_high - cnt_is_15_is_high =1)
- `value_hi` 和 `value_lo` 由下一行进行约束。即当 `cnt_prev != 0` 时,`value_hi` 和 `value_lo` 均与上一行相等。因此 PUSH 指令的所有行的 `value_hi` 和 `value_lo` 均等于 PUSH 的最后一个 byte 的 `value_hi` 和 `value_lo`:
cnt_prev !=0 ----> `acc_hi_prev + is_high*(acc_hi_prev*255 + bytecode) - acc_hi_cur =0`(约束acc_hi)
```
value_hi 和 value_lo 的最终值等于 PUSH 的最后一个 byte 的 value_hi 和 value_lo
```
&emsp;&emsp;cnt_prev !=0 && is_high=0 ----> `acc_hi_cur-acc_hi_prev=0` (cnt < 16的行,acc_hi的值是不变的)
#### **cnt_prev != 0**
&emsp;&emsp;cnt_prev !=0 && is_high=1 ----> `acc_hi_prev*256 + bytecode - acc_hi_cur =0` (即acc_hi_cur的值为`acc_pre*256+bytecoce`)
当 `cnt_prev != 0` 时,表示当前行是 PUSH 指令的字节:
cnt_prev !=0 ----> `acc_lo_cur - acc_lo_prev - (1-is_high) *(acc_lo_prev*255 + bytecode)=0` (约束acc_lo,当cnt < 16, 即high=0时,acc_lo_cur=acc_lo_prev*256 + bytecode)
- `cnt` 是递减的:
cnt_prev != 0 ----> value_hi_prev - value_hi_cur=0, value_lo_prev-value_lo_cur=0
```
cnt_prev != 0 ----> cnt_prev - cnt_cur = 1
```
**PUSH的最后一个byte:**
- 用于约束 `cnt = 15` 和 `cnt = 16` 的分界线:
cnt_prev!=0, cnt=0,value_hi=acc_hi, value_lo=acc_lo
```
cnt_prev != 0 -----> is_high_prev - is_high_cur - cnt_is_15 = 0
```
**rlc_acc**
- 约束 `acc_hi` 的值:
addr change ----> rlc_acc=bytecode (addr发生变化,说明是一个新的合约,rlc_acc开始)
```
cnt_prev != 0 ----> acc_hi_prev + is_high * (acc_hi_prev * 256 + bytecode) - acc_hi_cur = 0
```
addr unchange && addr != 0 ----> rlc_acc = rlc_acc_prev * challenge + bytecode (rlc_acc累加)
当 `is_high = 0` 时,`acc_hi` 的值不变:
**hash_hi和hash_lo**
```
cnt_prev != 0 && is_high = 0 ----> acc_hi_cur - acc_hi_prev = 0
```
addr_unchange_next != 0时,即下一行的addr change,下一行是新合约的开始,则当前行存放有合约的hash值(hash_hi和hash_lo的值不为0)
当 `is_high = 1` 时,`acc_hi_cur` 的值为 `acc_hi_prev * 256 + bytecode`:
所以只要addr_is_not_zero && addr_unchange_next != 0 则hash_hi和hash_lo都为0
```
cnt_prev != 0 && is_high = 1 ----> acc_hi_prev * 256 + bytecode - acc_hi_cur = 0
```
## Lookup约束
- 约束 `acc_lo` 的值:
每一个byte都应该在fixed电路中Lookup到,即每一个字节大小都应该在0~255范围内~~(是否真的有必要进行Lookup,因为bytecode列是从instance_bytecode来的,是公共数据)~~
```
cnt_prev != 0 ----> acc_lo_cur - acc_lo_prev - (1 - is_high) * (acc_lo_prev * 256 + bytecode) = 0
```
Lookup Fixed table, 约束Bytecode是否为正确的Opcode, <tag=Bytecode, bytecode, is_push, cnt>
当 `cnt < 16` 时,即 `is_high = 0`,`acc_lo_cur` 的值为 `acc_lo_prev * 256 + bytecode`。
Lookup keccak table,<pc+1(即length), rlc_acc, hash_hi, hash_lo> 去往Keccak table查。此lookup只在下一行的addr change==0时进行(即合约的最后一个bytecode所在行存放着合约bytecode的hash值)。
- `value_hi` 和 `value_lo` 的值保持不变:
Lookup Public table,addr和hash新增的往public table的lookup。<tag=CodeHash, addr, hash_hi, hash_lo>。此lookup只在下一行的addr change==0时进行。
```
cnt_prev != 0 ----> value_hi_prev - value_hi_cur = 0, value_lo_prev - value_lo_cur = 0
```
#### **PUSH 的最后一个 byte**
- `cnt_prev != 0` 且 `cnt = 0` 时,`value_hi` 和 `value_lo` 的值等于 `acc_hi` 和 `acc_lo`:
```
cnt_prev != 0, cnt = 0 ----> value_hi = acc_hi, value_lo = acc_lo
```
#### rlc_acc
- 当地址发生变化时,`rlc_acc` 为当前 `bytecode`:
```
addr change ----> rlc_acc = bytecode
```
- 当地址未发生变化且地址不为 0 时,`rlc_acc` 累加:
```
addr unchange && addr != 0 ----> rlc_acc = rlc_acc_prev * challenge + bytecode
```
#### **hash_hi 和 hash_lo**
- 当下一行的地址发生变化时,当前行存放有合约的哈希值:
```
addr_unchange_next != 0 ----> hash_hi 和 hash_lo 不为 0
```
- 其他情况下,`hash_hi` 和 `hash_lo` 的值均为 0:
```
addr_is_not_zero && addr_unchange_next != 0 ----> hash_hi 和 hash_lo 为 0
```
## Lookup约束
每一个byte都应该在fixed电路中Lookup到,即每一个字节大小都应该在0~255范围内。
**Lookup Fixed table**:约束Bytecode是否为正确的Opcode,格式为`<tag=Bytecode, bytecode, is_push, cnt>`。
**Lookup keccak table**:格式为`<pc+1(即length), rlc_acc, hash_hi, hash_lo>`,仅在下一行的`addr change==0`时进行。
**Lookup Public table**:格式为`<tag=CodeHash, addr, hash_hi, hash_lo>`,仅在下一行的`addr change==0`时进行。
## 2024-07-01更新
......@@ -242,8 +328,6 @@ bytecode可能存在一种情况,在bytecode末尾的PUSH可能存在push字
keccak计算hash时不算这部分padding的值
### 新加约束
length: `length_cur == length_prev`
......
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号