Skip to content

Latest commit

 

History

History
77 lines (71 loc) · 3.49 KB

File metadata and controls

77 lines (71 loc) · 3.49 KB

Range Check

代码:

上一讲说到在 example3_broken.rs 中下面的代码会导致报错:

// THIS IS BROKEN!!!!!!
// Hint: consider the case where q_lookup = 0. What are our input expressions to the lookup argument then?
vec![
    (q_lookup.clone() * num_bits, table.num_bits),
    (q_lookup.clone() * value, table.value),
]

原因是这里没有考虑到有的行不启用 q_lookup ,也就是置 q_lookup = 0,这时就要查找 (0, 0) 是否在 (num_bits, table) 里面了,实际上是不在的,在 table.rs 代码中定义了查找表,查看表的 load 方法。

pub(super) fn load(&self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
    layouter.assign_table(
        || "load range-check table", 
        |mut table| {
            let mut offset = 0;

            // Assign (num_bits = 1, value = 0)
            {
                table.assign_cell(
                    || "assign num_bits", 
                    self.num_bits, 
                    offset, 
                    || Value::known(F::one()),
                )?;
                table.assign_cell(
                    || "assign value", 
                    self.value, 
                    offset, 
                    || Value::known(F::zero()),
                )?;

                offset += 1;
            }

            for num_bits in 1..=NUM_BITS {
                for value in (1 << (num_bits - 1))..(1 << num_bits) {
                    table.assign_cell(
                        || "assign num_bits", 
                        self.num_bits, 
                        offset, 
                        || Value::known(F::from(num_bits as u64)),
                    )?;
                    table.assign_cell(
                        || "assign value", 
                        self.value, 
                        offset, 
                        || Value::known(F::from(value as u64)),
                    )?;
                    offset += 1;
                }
            }

            Ok(())
        }
    )
}  

可以看到 num_bits 是从 1 开始定义的,自然 (0, 0)肯定不在查找表里,因此就会报错。那我们这里要对那些没有启用查找表的行,定义为默认在表中的元素,这样在这些行依然能满足约束。下面定义的默认值为 (default_num_bits, defalut_value) = (1, 0),选取其他在查找表中的任意一对值也是可以的。定义 not_q_lookup 为没有启用查找行的值,接着和 q_lookup 线性组合下就可以了,具体如下:

let not_q_lookup = Expression::Constant(F::one()) - q_lookup.clone();
let default_num_bits = Expression::Constant(F::one());
let default_value = Expression::Constant(F::zero());
let num_bits_input = q_lookup.clone() * num_bits + not_q_lookup.clone() * default_num_bits;
let value_input = q_lookup.clone() * value + not_q_lookup.clone() * default_value;

vec![
    (num_bits_input, table.num_bits),
    (value_input, table.value),
]