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
  • 12 exp

Last edited by geruiwang Aug 12, 2024
Page history
This is an old version of this page. You can view the most recent version or browse the history.

12 exp

Exp

EXP 指令计算一个数的指数,例如 base^index,本文处理EXP指令以及电路中exp运算的子电路。

Witness、Column设计

Witness设计

#[derive(Clone, Debug, Serialize)]
pub struct Row {
    // type of row, one of zero, one, SQUARE or Bit
    pub tag: Tag,
    // base of exp
    pub base_hi: U256,
    pub base_lo: U256,
    // index of exp
    pub index_hi: U256,
    pub index_lo: U256,
    // count of index
    pub count: U256,
    // exp res
    pub power_hi: U256,
    pub power_lo: U256,
}

#[derive(Clone, Copy, Debug, Default, Serialize, EnumIter, EnumString)]
pub enum Tag {
    #[default]
    Zero,
    One,
    Square,
    Bit0, // index & 1 = 0
    Bit1, // index & 1 = 1
}

Circuit Column 设计

#[derive(Clone)]
pub struct ExpCircuitConfig<F: Field> {
    q_enable: Selector,
    /// the operation tag, zero,one,Bit,SQUARE
    pub tag: BinaryNumberConfig<Tag, LOG_NUM_EXP_TAG>,
    /// base hi , base lo
    pub base: [Column<Advice>; EXP_NUM_OPERAND],
    /// index hi, index lo
    pub index: [Column<Advice>; EXP_NUM_OPERAND],
    /// power hi, power lo
    pub power: [Column<Advice>; EXP_NUM_OPERAND],
    /// count
    pub count: Column<Advice>,
    /// IsZero chip for column count
    pub count_is_zero: IsZeroWithRotationConfig<F>,
    /// for chip to determine whether count is 128
    pub count_is_128: IsZeroConfig<F>,
    /// arithmetic table for lookup
    arithmetic_table: ArithmeticTable,
}

Witness生成算法设计

pub fn from_operands(
    base: U256,
    index: U256,
) -> (U256, Vec<Self>, Vec<arithmetic::Row>) {
  let base_hi = base >> 128;
  			...
        exp_rows.push(zero_row);
        if index.is_zero() {
            return (power_value, exp_rows, mul_row);
        }
        let one_row = Self {
          ...
        };
        exp_rows.push(one_row);
        let mut div = index.clone();
        let mut rem = U256::zero();
        loop {
            // first generate bit0/1  row
            (div, rem) = div.div_mod(U256::from(2));
            // then generate bit0/1
            let pre_pre_id = exp_rows.len() - 2;
            let pre_id = exp_rows.len() - 1;
            let (bit_index_hi, bit_index_lo, bit_val) = if rem.is_zero() {
                (
                    exp_rows[pre_pre_id].index_hi,
                    exp_rows[pre_pre_id].index_lo,
                    (exp_rows[pre_pre_id].power_hi << 128).add(exp_rows[pre_pre_id].power_lo),
                )
            } else {
                let pre_pre_index_hi = exp_rows[pre_pre_id].index_hi;
                let pre_pre_index_lo = exp_rows[pre_pre_id].index_lo;
                let pre_index_hi = exp_rows[pre_id].index_hi;
                let pre_index_lo = exp_rows[pre_id].index_lo;
                let pre_pre_val =
                    (exp_rows[pre_pre_id].power_hi << 128).add(exp_rows[pre_pre_id].power_lo);
                let pre_val = (exp_rows[pre_id].power_hi << 128).add(exp_rows[pre_id].power_lo);
                let (pre_pre_val_mul_pre_val_rows, pre_pre_val_mul_pre_val_result) =
                    operation::mul::gen_witness(vec![pre_pre_val, pre_val]);
                mul_row.extend(pre_pre_val_mul_pre_val_rows);
                (
                    pre_pre_index_hi.add(pre_index_hi),
                    pre_pre_index_lo.add(pre_index_lo),
                    pre_pre_val_mul_pre_val_result[0],
                )
            };
            let bit_row = Self {
  					...
            if div.is_zero() {
                break;
            }
          let pre_pre_id = exp_rows.len() - 2;
            let pre_id = exp_rows.len() - 1;
            let pre_count = exp_rows[pre_id].count;
            // use arithmetic mul
            // pre_pre_power * pre_pre_power
            let pre_pre_val =
                (exp_rows[pre_pre_id].power_hi << 128).add(exp_rows[pre_pre_id].power_lo);
            let count = pre_count.add(U256::one());
            let (index_hi, index_lo) = if count.eq(&U256::from(128)) {
                (U256::one(), U256::zero())
            } else {
                (
                    exp_rows[pre_pre_id].index_hi.mul(2),
                    exp_rows[pre_pre_id].index_lo.mul(2),
                )
            };
            // pre_pre_power * pre_pre_power
            let (val_mul_val_rows, val_mul_val_result) =
                operation::mul::gen_witness(vec![pre_pre_val, pre_pre_val]);
            mul_row.extend(val_mul_val_rows);
            // first generate square
            let square_row = Self {
                tag: Tag::Square,
                base_hi,
                base_lo,
                index_hi: index_hi,
                index_lo: index_lo,
                count,
                // is_high,
                power_hi: val_mul_val_result[0] >> 128,
                power_lo: val_mul_val_result[0].low_u128().into(),
            };
            exp_rows.push(square_row);
          ...
}

详细代码参考/zkevm/zkevm-circuits/src/witness/exp.rs

入参:

  • base: 底数
  • index: 指数

返回参数:

  • exp运算结果
  • exp生成的witness row数组(exp rows)
  • 使用乘法电路运算生成的witness row(mul rows)

算法:

  • 生成Tag::Zero 行,将其添加到exp rows中
  • 若index == 0,则直接返回
  • 生成Tag::One 行, 将其添加到exp rows中
  • 循环对 div 做2的除法和取模运算,记商为div,余数为rem
    • 生成Tag::Bit0/Tag::Bit1 Row;其中count = (exp rows中的前一行的row)的count
      • 若rem == 0 , 则生成Tag::Bit0 Row,将其添加到exp rows中;其中index hi/lo = (exp rows中的两行前的row)的 index hi/lo;power hi/lo = (exp rows中的两行前的row)的 power hi/lo
      • 若rem == 1 , 则生成Tag::Bit1 Row,将其添加到exp rows中;其中index hi/lo = (exp rows中的两行前的row)的 index hi/lo + (exp rows中的前一行的row)的index hi/lo;power hi/lo = (exp rows中的两行前的row)的 power hi/lo * (exp rows中的前一行的row)的 power hi/lo,调用乘法电路生成mul row,将其添加到mul rows中
    • 若div == 0, 则中断循环
    • 否则:
      • 生成Tag::SQUARE Row,将其添加到exp rows中;count = (exp rows中的前一行的row)的count + 1;若count = 128,则index hi = 1; index lo = 0; 若count <> 128,则index hi/lo = (exp rows中的两行前的row)的 index hi/lo * 2 ;power hi/lo = (exp rows中的两行前的row)的 power hi/lo 的平方,调用乘法电路生成mul row,将其添加到mul rows中;
  • 去exp rows中最后一行的power hi/lo, 将power hi << 128 + power lo作为最终的power value, return (power value,exp rows, mul rows)

门约束

Base hi/lo 约束

  • 若当前行的Tag为ONE、SQUARE、BIT0、BIT1,则base hi/lo等于前一行的base hi/lo

Tag 约束

  • 若当前行的Tag为ZERO,则前一行的Tag为ZERO、BIT1或BIT0
  • 若当前行的Tag为SQUARE,则前一行的Tag必为Bit0或Bit1
  • 若当前行的Tag为ONE,则前一行的Tag必为ZERO
  • 若当前行的Tag为Bit0或Bit1,则前一行的Tag为ONE或SQUARE

Count约束

  • 若当前行的Tag为ZERO,则count为0
  • 若当前行的Tag为ONE,则count为0
  • 若当前行的Tag为SQUARE,则count为前一行的count + 1
  • 若当前行的Tag为Bit0或Bit1,则count等于前一行的count

Index/Power约束

  • 若当前行的Tag为ZERO,则index为0,power为1

  • 若当前行的Tag为ONE,则index为1,power为BASE(底数)

  • 若当前行的Tag为Bit0,则index等于前两行的index,power等于前两行的power

  • 若当前行的Tag为SQUARE,且count为128,则index hi为1,index lo为0

  • 若当前行的Tag为SQUARE,且count不等于128,则index hi/lo等于两行前的index hi/lo乘以2

  • 若当前行的Tag为Bit1,则index hi/lo等于两行前的index hi/lo与前一行的index hi/lo之和

  • 若当前行的Tag为ZERO,则index为0,power为1,则index

  • 若当前行的Tag为ONE,则index为1,power为BASE(底数)

  • 若当前行的Tag为Bit0,则index等于前两行index,power等于前两行的power

  • 若当前行的Tag为SQUARE,且count为128,则index hi为1,index lo为0

  • 若当前行的Tag为SQUARE,且count不等于128,则index hi/lo 等于两行前的index hi/lo * 2

  • 若当前行的Tag为Bit1,则index hi/lo 等于两行前的 index hi/lo 与 前一行的 index hi/lo 之和

Lookup约束

Tag为SQUARE,Power运算lookup

  • 若Tag为SQUARE,则power为两行前的power的平方

Tag为Bit1,Power运算lookup

若Tag为Bit1,则power为两行前的power乘以前一行的power

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号