| ... | @@ -84,9 +84,7 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
... | @@ -84,9 +84,7 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
| 
 | 
  - define carry_hi = (t2 + (t3 << 64) + c_hi + carry_lo).saturating_sub(d_hi) >> 128
 | 
 | 
  - define carry_hi = (t2 + (t3 << 64) + c_hi + carry_lo).saturating_sub(d_hi) >> 128
 | 
| 
 | 
  ```
 | 
 | 
  ```
 | 
| 
 | 
  - 如果是 0 行,约束 num_row is 10,并且约束 cnt 自增的有效性
 | 
 | 
  - 如果是 0 行,约束 num_row is 10,并且约束 cnt 自增的有效性
 | 
| 
 | 
  - a_lo = u16 sum(rotation cur)
 | 
 | 
  - b_lo = u16 sum(rotation -2) //请注意因为a是输入值,我们可以不对a_hi,a_lo进行range约束
 | 
| 
 | 
  - a_hi = u16 sum(rotation -1)
 | 
 | 
 | 
| 
 | 
  - b_lo = u16 sum(rotation -2)
 | 
 | 
 | 
| 
 | 
  - b_hi = u16 sum(rotation -3)
 | 
 | 
  - b_hi = u16 sum(rotation -3)
 | 
| 
 | 
  - c_lo = u16 sum(rotation -4)
 | 
 | 
  - c_lo = u16 sum(rotation -4)
 | 
| 
 | 
  - c_hi = u16 sum(rotation -5)
 | 
 | 
  - c_hi = u16 sum(rotation -5)
 | 
| ... | @@ -153,30 +151,52 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
... | @@ -153,30 +151,52 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
| 
 | 
  - d = pop1
 | 
 | 
  - d = pop1
 | 
| 
 | 
  ```
 | 
 | 
  ```
 | 
| 
 | 
  - a_abs,b_abs,c_abs,d_abs
 | 
 | 
  - a_abs,b_abs,c_abs,d_abs
 | 
| 
 | 
  ``
 | 
 | 
  ```
 | 
| 
 | 
  关于补码的相关约束如下
 | 
 | 
  关于补码的相关约束如下
 | 
| 
 | 
  - x_abs_lo == lo when x >= 0
 | 
 | 
  - x_abs_lo == lo when x >= 0
 | 
| 
 | 
  - x_abs_hi == hi when x < 0
 | 
 | 
  - x_abs_hi == hi when x >= 0
 | 
| 
 | 
  - sum == 0 when x < 0 (小于0证明存在补码,同时我们有x+x_abs = 1 <<256。x + x_abs 约束请参考add部分)
 | 
 | 
  - sum == 0 when x < 0 (小于0证明存在补码,同时我们有x+x_abs = 1 <<256。x + x_abs 约束请参考add部分)
 | 
| 
 | 
  - carry_hi == 1 when x < 0
 | 
 | 
  - carry_hi == 1 when x < 0
 | 
| 
 | 
  ``
 | 
 | 
  ```
 | 
| 
 | 
  - mul_add_words (请参考mul部分约束内容)
 | 
 | 
  - mul_add_words (请参考mul部分约束内容)
 | 
| 
 | 
  - abs(remainder) < abs(divisor) when divisor != 0
 | 
 | 
  - abs(remainder) < abs(divisor) when divisor != 0
 | 
| 
 | 
  - mul_add_words中的carry_hi == 0
 | 
 | 
  - mul_add_words中的carry_hi == 0
 | 
| 
 | 
  - sign(dividend) == sign(remainder) when quotient, divisor and remainder are all non-zero。 这里主要是有mod的值与被除数的符号相同
 | 
 | 
  - sign(dividend) == sign(remainder) when quotient, divisor and remainder are all non-zero。 这里主要是有mod的值与被除数的符号相同
 | 
| 
 | 
  - quotient_abs_word.is_neg().expr() + divisor_abs_word.is_neg().expr()
 | 
 | 
  - quotient_abs_word.is_neg().expr() + divisor_abs_word.is_neg().expr() (如果被除数的补码也是负数,与余数和除数等于零,则排除约束情况) 这里说到的符号都是非补码的符号
 | 
| 
 | 
    - dividend_abs_word.is_neg().expr()
 | 
 | 
    - dividend_abs_word.is_neg().expr()
 | 
| 
 | 
    - 2.expr()
 | 
 | 
    - 2.expr()
 | 
| 
 | 
    * quotient_abs_word.is_neg().expr()
 | 
 | 
    * quotient_abs_word.is_neg().expr()
 | 
| 
 | 
    * divisor_abs_word.is_neg().expr(),
 | 
 | 
    * divisor_abs_word.is_neg().expr(),  这里计算的都是div情况下的变化
 | 
| 
 | 
 | 
 | 
 | 
| 
 | 
 | 
 | 
 | 
| 
 | 
- AddMod 计算addMod操作码我们等于验证a,b,n,r 其中n是mod值,r是余数。我们有(a+b)%n = r。我们可以将这个约束转化为(a+b) = n * q + r。为了约束简单我们可以有
 | 
 | 
- AddMod 计算addMod操作码我们等于验证a,b,n,r 其中n是mod值,r是余数。我们有(a+b)%n = r。我们可以将这个约束转化为(a+b) = n * q + r。为了约束简单我们可以有
 | 
| 
 | 
  a % n= a_div_n + a_remainder
 | 
 | 
  a % n= a_div_n + a_remainder a = n * a_div_n + a_remainder
 | 
| 
 | 
  (a_remainder + b) = (a_remainder_plus_b +a_remainder_plus_b_overflow << 256 ) % n= b_div_n + r
 | 
 | 
  (a_remainder + b) = (a_remainder_plus_b +a_remainder_plus_b_overflow << 256 )
 | 
| 
 | 
   其中a_remainder+b 大于256位,我们可以有以下约束 
 | 
 | 
  (a_remainder_plus_b + a_remainder_plus_b_overflow << 256 ) % n= b_div_n + r
 | 
 | 
 | 
 | 
   note: 其中a_remainder+b 大于256位. 我们可以有以下约束 
 | 
 | 
 | 
 | 
```
 | 
 | 
 | 
 | 
/// Construct the gadget that checks a * b + c == d * 2**256 + e
 | 
 | 
 | 
 | 
/// where a, b, c, d, e are 256-bit words.
 | 
 | 
 | 
 | 
///
 | 
 | 
 | 
 | 
/// We execute a multi-limb multiplication as follows:
 | 
 | 
 | 
 | 
/// a and b is divided into 4 64-bit limbs, denoted as a0~a3 and b0~b3
 | 
 | 
 | 
 | 
/// defined t0, t1, t2, t3, t4, t5, t6:
 | 
 | 
 | 
 | 
///   t0 = a0 * b0, // 0 - 128bit
 | 
 | 
 | 
 | 
///   t1 = a0 * b1 + a1 * b0, //64 - 193bit 两数相加可能存在进位
 | 
 | 
 | 
 | 
///   t2 = a0 * b2 + a2 * b0 + a1 * b1, //128 - 258bit
 | 
 | 
 | 
 | 
///   t3 = a0 * b3 + a3 * b0 + a2 * b1 + a1 * b2, //192 - 322bit
 | 
 | 
 | 
 | 
///   t4 = a1 * b3 + a2 * b2 + a3 * b1,
 | 
 | 
 | 
 | 
///   t5 = a2 * b3 + a3 * b2,
 | 
 | 
 | 
 | 
///   t6 = a3 * b3,
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
/// Finally we just prove: 
 | 
 | 
 | 
 | 
///   t0 + t1 * 2^64 + c_lo = e_lo + carry_0 * 2^128 // carry_0 is 65bit
 | 
 | 
 | 
 | 
///   t2 + t3 * 2^64 + c_hi + carry_0 = e_hi + carry_1 * 2^128
 | 
 | 
 | 
 | 
///   t4 + t5 * 2^64 + carry_1 = d_lo + carry_2 * 2^128
 | 
 | 
 | 
 | 
///   t6 + carry_2 = d_hi
 | 
 | 
 | 
 | 
```
 | 
| 
 | 
  - a,n,a_remainder,a_div_n 存在mul_add_words约束 a_div_n * n + a_remainder = a
 | 
 | 
  - a,n,a_remainder,a_div_n 存在mul_add_words约束 a_div_n * n + a_remainder = a
 | 
| 
 | 
  - b,a_remainder,a_remainder_plus_b 存在add_words约束 a_remainder + b = a_remainder_plus_b
 | 
 | 
  - b,a_remainder,a_remainder_plus_b 存在add_words约束 a_remainder + b = a_remainder_plus_b + a_remainder_plus_b_overflow << 256
 | 
| 
 | 
  - b_div_n,n,b_remainder,a_reduced_plus_b_overflow 存在mul_add_words约束 b_div_n * n + r = a_remainder_plus_b + a_remainder_plus_b_overflow << 256 (mul_add_512_gadget)
 | 
 | 
  - b_div_n,n,b_remainder,a_reduced_plus_b_overflow 存在mul_add_words约束 b_div_n * n + r = a_remainder_plus_b + a_remainder_plus_b_overflow << 256 (mul_add_512_gadget)
 | 
| 
 | 
  - a_remainder < n 约束
 | 
 | 
  - a_remainder < n 约束
 | 
| 
 | 
  - r < n 约束
 | 
 | 
  - r < n 约束
 | 
| ... | @@ -184,16 +204,19 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
... | @@ -184,16 +204,19 @@ operand* 用来存放算术中的参数值,如 a+b=c+overflow 指令中的 a,b | 
| 
 | 
 | 
 | 
 | 
| 
 | 
 | 
 | 
 | 
| 
 | 
- MulMod 计算mulMod操作码我们等于验证a,b,n,r 其中n是mod值,r是余数。我们有a*b%n = r。我们可以将这个约束转化为a*b = n * q + r。为了约束简单我们可以有
 | 
 | 
- MulMod 计算mulMod操作码我们等于验证a,b,n,r 其中n是mod值,r是余数。我们有a*b%n = r。我们可以将这个约束转化为a*b = n * q + r。为了约束简单我们可以有
 | 
| 
 | 
  a % n= a_div_n + a_remainder
 | 
 | 
  a % n= a_div_n + a_remainder  -> a = n * a_div_n + a_remainder
 | 
| 
 | 
  a_remainder * b =pordut & n= b_div_n + r
 | 
 | 
  a_remainder * b =product & n= b_div_n + r
 | 
| 
 | 
  pordut是512bit,我们将它分为两个256bit的数,pordut_hi,pordut_lo。我们可以有以下约束
 | 
 | 
  product是512bit,我们将它分为两个256bit的数,product_hi,product_lo。我们可以有以下约束
 | 
| 
 | 
  - a,n,a_remainder,a_div_n 存在mul_add_words约束
 | 
 | 
  - a,n,a_remainder,a_div_n 存在mul_words约束
 | 
| 
 | 
  - b,a_remainder,pordut_hi,pordut_lo 存在mul_add_words约束,请注意这里b*a_remainder的结果等于pordut是512bit
 | 
 | 
  - b,a_remainder,product_hi,product_lo 存在mul_add_words约束,请注意这里b*a_remainder的结果等于port是512bit.我们最后有product_hi * 2^256 + product_lo = b * a_remainder
 | 
| 
 | 
  - pordut_hi,pordut_lo,n,b_div_n,r 存在mul_add_words约束,同样需要注意这里n * b_div_n + r 的结果等于pordut是512bit
 | 
 | 
  - product_hi,product_lo,n,b_div_n,r 存在mul_add_words约束,同样需要注意这里n * b_div_n + r 的结果等于product是512bit.我们最后有product_hi * 2^256 + product_lo = n * b_div_n + r
 | 
 | 
 | 
 | 
  - a_remainder < n 约束
 | 
| 
 | 
  - r < n 约束
 | 
 | 
  - r < n 约束
 | 
| 
 | 
  - n_is_zero 约束
 | 
 | 
  - n_is_zero 约束
 | 
| 
 | 
  
 | 
 | 
  
 | 
| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
| 
 | 
- Length 
 | 
 | 
- Length 
 | 
| 
 | 
  arithmetic中的布局: 
 | 
 | 
  arithmetic中的布局: 
 | 
| 
 | 
 | 
 | 
 | 
| ... |  | ... |  |