Improve BIGNUM operations (#1482)

This commit is contained in:
Robin Salen 2024-01-24 05:03:49 -05:00 committed by GitHub
parent acc59c3563
commit c0700065db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 306 additions and 297 deletions

View File

@ -9,49 +9,55 @@ global add_bignum:
ISZERO
%jumpi(len_zero)
// stack: len, a_start_loc, b_start_loc, retdest
%build_current_general_address_no_offset
PUSH 0
// stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, retdest
// stack: carry=0, base_addr, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, retdest
add_loop:
// stack: carry, i, a_cur_loc, b_cur_loc, retdest
DUP4
%mload_current_general
// stack: b[cur], carry, i, a_cur_loc, b_cur_loc, retdest
DUP4
%mload_current_general
// stack: a[cur], b[cur], carry, i, a_cur_loc, b_cur_loc, retdest
ADD
ADD
// stack: a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest
DUP1
// stack: a[cur] + b[cur] + carry, a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest
%shr_const(128)
// stack: (a[cur] + b[cur] + carry) // 2^128, a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest
SWAP1
// stack: a[cur] + b[cur] + carry, (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest
%mod_const(0x100000000000000000000000000000000)
// stack: c[cur] = (a[cur] + b[cur] + carry) % 2^128, carry_new = (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest
DUP4
// stack: a_cur_loc, c[cur], carry_new, i, a_cur_loc, b_cur_loc, retdest
%mstore_current_general
// stack: carry_new, i, a_cur_loc, b_cur_loc, retdest
SWAP2
%increment
SWAP2
// stack: carry_new, i, a_cur_loc + 1, b_cur_loc, retdest
SWAP3
%increment
SWAP3
// stack: carry_new, i, a_cur_loc + 1, b_cur_loc + 1, retdest
SWAP1
%decrement
SWAP1
// stack: carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
// stack: carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
DUP2
// stack: i - 1, carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
// stack: base_addr, carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
DUP6 ADD // base_addr + b_cur_loc
MLOAD_GENERAL
// stack: b[cur], carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
DUP3
DUP6 ADD // base_addr + a_cur_loc
MLOAD_GENERAL
// stack: a[cur], b[cur], carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
ADD
ADD
// stack: a[cur] + b[cur] + carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
DUP1
// stack: a[cur] + b[cur] + carry, a[cur] + b[cur] + carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
%shr_const(128)
// stack: (a[cur] + b[cur] + carry) // 2^128, a[cur] + b[cur] + carry, base_addr, i, a_cur_loc, b_cur_loc, retdest
SWAP1
// stack: a[cur] + b[cur] + carry, (a[cur] + b[cur] + carry) // 2^128, base_addr, i, a_cur_loc, b_cur_loc, retdest
%mod_const(0x100000000000000000000000000000000)
// stack: c[cur] = (a[cur] + b[cur] + carry) % 2^128, carry_new = (a[cur] + b[cur] + carry) // 2^128, base_addr, i, a_cur_loc, b_cur_loc, retdest
DUP3
DUP6
ADD // base_addr + a_cur_loc
// stack: a_cur_addr, c[cur], carry_new, base_addr, i, a_cur_loc, b_cur_loc, retdest
%swap_mstore
// stack: carry_new, base_addr, i, a_cur_loc, b_cur_loc, retdest
SWAP3
%increment
SWAP3
// stack: carry_new, base_addr, i, a_cur_loc + 1, b_cur_loc, retdest
SWAP4
%increment
SWAP4
// stack: carry_new, base_addr, i, a_cur_loc + 1, b_cur_loc + 1, retdest
SWAP2
%decrement
SWAP2
// stack: carry_new, base_addr, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
DUP3
// stack: i - 1, carry_new, base_addr, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
%jumpi(add_loop)
add_end:
// stack: carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
%stack (c, i, a, b) -> (c)
// stack: carry_new, base_addr, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest
%stack (c, addr, i, a, b) -> (c)
// stack: carry_new, retdest
SWAP1
// stack: retdest, carry_new

View File

@ -8,95 +8,99 @@ global addmul_bignum:
// stack: len, len, a_start_loc, b_start_loc, val, retdest
ISZERO
%jumpi(len_zero)
%build_current_general_address_no_offset
PUSH 0
// stack: carry_limb=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest
// stack: carry_limb=0, base_addr, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest
addmul_loop:
// stack: carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
DUP4
// stack: b_cur_loc, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
%mload_current_general
// stack: b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
DUP6
// stack: val, b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP2
DUP6 ADD // base_addr + b_cur_loc
// stack: b_cur_addr, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
MLOAD_GENERAL
// stack: b[cur], carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP7
// stack: val, b[cur], carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
MUL
// stack: val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: val * b[cur], carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP1
// stack: val * b[cur], val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: val * b[cur], val * b[cur], carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
%shr_const(128)
// stack: (val * b[cur]) // 2^128, val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: (val * b[cur]) // 2^128, val * b[cur], carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP1
// stack: val * b[cur], (val * b[cur]) // 2^128, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: val * b[cur], (val * b[cur]) // 2^128, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
%shl_const(128)
%shr_const(128)
// stack: prod_lo = val * b[cur] % 2^128, prod_hi = (val * b[cur]) // 2^128, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
DUP5
// stack: a_cur_loc, prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
%mload_current_general
// stack: a[cur], prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo = val * b[cur] % 2^128, prod_hi = (val * b[cur]) // 2^128, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP4
DUP7 ADD // base_addr + a_cur_loc
// stack: a_cur_addr, prod_lo, prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
MLOAD_GENERAL
// stack: a[cur], prod_lo, prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP1
// stack: a[cur], a[cur], prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: a[cur], a[cur], prod_lo, prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP2
// stack: prod_lo, a[cur], a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo, a[cur], a[cur], prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
ADD
%shl_const(128)
%shr_const(128)
// stack: prod_lo' = (prod_lo + a[cur]) % 2^128, a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo' = (prod_lo + a[cur]) % 2^128, a[cur], prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP1
// stack: prod_lo', prod_lo', a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo', prod_lo', a[cur], prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP2
// stack: a[cur], prod_lo', prod_lo', prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: a[cur], prod_lo', prod_lo', prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
GT
// stack: prod_lo_carry_limb = a[cur] > prod_lo', prod_lo', prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo_carry_limb = a[cur] > prod_lo', prod_lo', prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP1
// stack: prod_lo', prod_lo_carry_limb, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo', prod_lo_carry_limb, prod_hi, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP2
// stack: prod_hi, prod_lo_carry_limb, prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_hi, prod_lo_carry_limb, prod_lo', carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
ADD
// stack: prod_hi' = prod_hi + prod_lo_carry_limb, prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_hi' = prod_hi + prod_lo_carry_limb, prod_lo', carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP3
// stack: carry_limb, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: carry_limb, prod_hi', prod_lo', carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP3
// stack: prod_lo', carry_limb, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo', carry_limb, prod_hi', prod_lo', carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
ADD
%shl_const(128)
%shr_const(128)
// stack: to_write = (prod_lo' + carry_limb) % 2^128, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: to_write = (prod_lo' + carry_limb) % 2^128, prod_hi', prod_lo', carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP2
// stack: prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: prod_lo', prod_hi', to_write, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP3
// stack: to_write, prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
// stack: to_write, prod_lo', prod_hi', to_write, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
LT
// stack: carry_limb_new = to_write < prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
%stack (vals: 3, c) -> (vals)
// stack: carry_limb_new, prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest
// stack: carry_limb_new, prod_hi', to_write, addr, i, a_cur_loc, b_cur_loc, val, retdest
ADD
// stack: carry_limb = carry_limb_new' + prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest
// stack: carry_limb = carry_limb_new' + prod_hi', to_write, addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP1
// stack: to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
DUP4
// stack: a_cur_loc, to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
%mstore_current_general
// stack: carry_limb, i, a_cur_loc, b_cur_loc, val, retdest
SWAP1
// stack: i, carry_limb, a_cur_loc, b_cur_loc, val, retdest
%decrement
// stack: i-1, carry_limb, a_cur_loc, b_cur_loc, val, retdest
// stack: to_write, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
DUP3
DUP6 ADD // base_addr + a_cur_loc
// stack: a_cur_addr, to_write, carry_limb, addr, i, a_cur_loc, b_cur_loc, val, retdest
%swap_mstore
// stack: carry_limb, base_addr, i, a_cur_loc, b_cur_loc, val, retdest
SWAP2
// stack: a_cur_loc, carry_limb, i-1, b_cur_loc, val, retdest
%increment
// stack: a_cur_loc+1, carry_limb, i-1, b_cur_loc, val, retdest
// stack: i, base_addr, carry_limb, a_cur_loc, b_cur_loc, val, retdest
%decrement
// stack: i-1, base_addr, carry_limb, a_cur_loc, b_cur_loc, val, retdest
SWAP3
// stack: b_cur_loc, carry_limb, i-1, a_cur_loc+1, val, retdest
// stack: a_cur_loc, base_addr, carry_limb, i-1, b_cur_loc, val, retdest
%increment
// stack: b_cur_loc+1, carry_limb, i-1, a_cur_loc+1, val, retdest
%stack (b, c, i, a) -> (c, i, a, b)
// stack: carry_limb, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
DUP2
// stack: i-1, carry_limb, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
// stack: a_cur_loc+1, base_addr, carry_limb, i-1, b_cur_loc, val, retdest
SWAP4
// stack: b_cur_loc, base_addr, carry_limb, i-1, a_cur_loc+1, val, retdest
%increment
// stack: b_cur_loc+1, base_addr, carry_limb, i-1, a_cur_loc+1, val, retdest
%stack (b, addr, c, i, a) -> (c, addr, i, a, b)
// stack: carry_limb, base_addr, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
DUP3
// stack: i-1, carry_limb, base_addr, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
%jumpi(addmul_loop)
addmul_end:
// stack: carry_limb_new, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
%stack (c, i, a, b, v) -> (c)
// stack: carry_limb_new, base_addr, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest
%stack (c, addr, i, a, b, v) -> (c)
// stack: carry_limb_new, retdest
SWAP1
// stack: retdest, carry_limb_new

View File

@ -5,82 +5,87 @@
// Returns 1 if a > b, 0 if a == b, and -1 (that is, 2^256 - 1) if a < b.
global cmp_bignum:
// stack: len, a_start_loc, b_start_loc, retdest
DUP1
// stack: len, len, a_start_loc, b_start_loc, retdest
%build_current_general_address_no_offset
// stack: base_addr, len, a_start_loc, b_start_loc, retdest
DUP2
// stack: len, base_addr, len, a_start_loc, b_start_loc, retdest
ISZERO
%jumpi(equal)
// stack: len, a_start_loc, b_start_loc, retdest
SWAP1
// stack: a_start_loc, len, b_start_loc, retdest
PUSH 1
DUP3
SUB
// stack: len-1, a_start_loc, len, b_start_loc, retdest
ADD
// stack: a_end_loc, len, b_start_loc, retdest
%jumpi(equal) // len and base_addr are swapped, but they will be popped anyway
// stack: base_addr, len, a_start_loc, b_start_loc, retdest
SWAP2
// stack: b_start_loc, len, a_end_loc, retdest
// stack: a_start_loc, len, base_addr, b_start_loc, retdest
PUSH 1
DUP3
SUB
// stack: len-1, b_start_loc, len, a_end_loc, retdest
// stack: len-1, a_start_loc, len, base_addr, b_start_loc, retdest
ADD
// stack: b_end_loc, len, a_end_loc, retdest
%stack (b, l, a) -> (l, a, b)
// stack: len, a_end_loc, b_end_loc, retdest
// stack: a_end_loc, len, base_addr, b_start_loc, retdest
SWAP3
// stack: b_start_loc, len, base_addr, a_end_loc, retdest
PUSH 1
DUP3
SUB
// stack: len-1, b_start_loc, len, base_addr, a_end_loc, retdest
ADD
// stack: b_end_loc, len, base_addr, a_end_loc, retdest
%stack (b, l, addr, a) -> (l, addr, a, b)
// stack: len, base_addr, a_end_loc, b_end_loc, retdest
%decrement
ge_loop:
// stack: i, a_i_loc, b_i_loc, retdest
DUP3
DUP3
// stack: a_i_loc, b_i_loc, i, a_i_loc, b_i_loc, retdest
%mload_current_general
SWAP1
%mload_current_general
SWAP1
// stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest
// stack: i, base_addr, a_i_loc, b_i_loc, retdest
DUP4
// stack: b_i_loc, i, base_addr, a_i_loc, b_i_loc, retdest
DUP3 ADD // b_i_addr
MLOAD_GENERAL
// stack: b[i], i, base_addr, a_i_loc, b_i_loc, retdest
DUP4
// stack: a_i_loc, b[i], i, base_addr, a_i_loc, b_i_loc, retdest
DUP4 ADD // a_i_addr
MLOAD_GENERAL
// stack: a[i], b[i], i, base_addr, a_i_loc, b_i_loc, retdest
%stack (vals: 2) -> (vals, vals)
GT
%jumpi(greater)
// stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest
// stack: a[i], b[i], i, base_addr, a_i_loc, b_i_loc, retdest
LT
%jumpi(less)
// stack: i, a_i_loc, b_i_loc, retdest
// stack: i, base_addr, a_i_loc, b_i_loc, retdest
DUP1
ISZERO
%jumpi(equal)
%decrement
// stack: i-1, a_i_loc, b_i_loc, retdest
SWAP1
// stack: a_i_loc, i-1, b_i_loc, retdest
%decrement
// stack: a_i_loc_new, i-1, b_i_loc, retdest
// stack: i-1, base_addr, a_i_loc, b_i_loc, retdest
SWAP2
// stack: b_i_loc, i-1, a_i_loc_new, retdest
// stack: a_i_loc, base_addr, i-1, b_i_loc, retdest
%decrement
// stack: b_i_loc_new, i-1, a_i_loc_new, retdest
%stack (b, i, a) -> (i, a, b)
// stack: i-1, a_i_loc_new, b_i_loc_new, retdest
// stack: a_i_loc_new, base_addr, i-1, b_i_loc, retdest
SWAP3
// stack: b_i_loc, base_addr, i-1, a_i_loc_new, retdest
%decrement
// stack: b_i_loc_new, base_addr, i-1, a_i_loc_new, retdest
%stack (b, addr, i, a) -> (i, addr, a, b)
// stack: i-1, base_addr, a_i_loc_new, b_i_loc_new, retdest
%jump(ge_loop)
equal:
// stack: i, a_i_loc, b_i_loc, retdest
%pop3
// stack: i, base_addr, a_i_loc, b_i_loc, retdest
%pop4
// stack: retdest
PUSH 0
// stack: 0, retdest
SWAP1
JUMP
greater:
// stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest
%pop5
// stack: a[i], b[i], i, base_addr, a_i_loc, b_i_loc, retdest
%pop6
// stack: retdest
PUSH 1
// stack: 1, retdest
SWAP1
JUMP
less:
// stack: i, a_i_loc, b_i_loc, retdest
%pop3
// stack: i, base_addr, a_i_loc, b_i_loc, retdest
%pop4
// stack: retdest
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// stack: -1, retdest

View File

@ -21,28 +21,32 @@ global modmul_bignum:
// STEP 1:
// The prover provides x := (a * b) % m, which we store in output_loc.
%build_current_general_address_no_offset
PUSH 0
// stack: i=0, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i=0, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
modmul_remainder_loop:
// stack: i, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
PROVER_INPUT(bignum_modmul)
// stack: PI, i, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP7
// stack: PI, i, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP8
DUP3
ADD
// stack: out_loc[i], PI, i, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%mstore_current_general
// stack: i, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: out_loc[i], PI, i, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP4 ADD // out_addr_i
%swap_mstore
// stack: i, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%increment
DUP3
DUP2
DUP2
// stack: i+1, len, i+1, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i+1, len, i+1, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
SUB // functions as NEQ
// stack: i+1!=len, i+1, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i+1!=len, i+1, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%jumpi(modmul_remainder_loop)
// end of modmul_remainder_loop
// stack: i, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
POP
// stack: i, base_addr, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%pop2
// stack: len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
@ -69,28 +73,32 @@ modmul_return_1:
// stack: len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%mul_const(2)
// stack: 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%build_current_general_address_no_offset
PUSH 0
// stack: i=0, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i=0, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
modmul_quotient_loop:
// stack: i, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
PROVER_INPUT(bignum_modmul)
// stack: PI, i, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP9
// stack: PI, i, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP10
DUP3
ADD
// stack: s1[i], PI, i, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%mstore_current_general
// stack: i, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: s1[i], PI, i, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
DUP4 ADD // s1_addr_i
%swap_mstore
// stack: i, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%increment
DUP3
DUP2
DUP2
// stack: i+1, 2*len, i+1, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i+1, 2*len, i+1, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
SUB // functions as NEQ
// stack: i+1!=2*len, i+1, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// stack: i+1!=2*len, i+1, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%jumpi(modmul_quotient_loop)
// end of modmul_quotient_loop
// stack: i, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%pop2
// stack: i, base_addr, 2*len, len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
%pop3
// stack: len, a_loc, b_loc, m_loc, out_loc, s1, s2, s3, retdest
// STEP 4:
@ -130,33 +138,36 @@ modmul_return_4:
// STEP 6:
// Check that x + k * m = a * b.
// Walk through scratch_2 and scratch_3, checking that they are equal.
// stack: n=len, i=s2, j=s3, retdest
%build_current_general_address_no_offset
// stack: base_addr, n=len, i=s2, j=s3, retdest
modmul_check_loop:
// stack: n, i, j, retdest
%stack (l, idx: 2) -> (idx, l, idx)
// stack: i, j, n, i, j, retdest
%mload_current_general
SWAP1
%mload_current_general
SWAP1
// stack: mem[i], mem[j], n, i, j, retdest
// stack: base_addr, n, i, j, retdest
%stack (addr, l, i, j) -> (j, i, addr, addr, l, i, j)
// stack: j, i, base_addr, base_addr, n, i, j, retdest
DUP3 ADD // addr_j
MLOAD_GENERAL
// stack: mem[j], i, base_addr, base_addr, n, i, j, retdest
SWAP2
ADD // addr_i
MLOAD_GENERAL
// stack: mem[i], mem[j], base_addr, n, i, j, retdest
%assert_eq
// stack: n, i, j, retdest
// stack: base_addr, n, i, j, retdest
SWAP1
%decrement
SWAP1
%increment
// stack: n-1, base_addr, i, j, retdest
SWAP2
%increment
SWAP2
SWAP1
// stack: n-1, i+1, j+1, retdest
DUP1
// stack: n-1, n-1, i+1, j+1, retdest
// stack: i+1, base_addr, n-1, j, retdest
SWAP3
%increment
// stack: j+1, base_addr, n-1, i+1, retdest
%stack (j, addr, n, i) -> (n, addr, n, i, j)
// stack: n-1, base_addr, n-1, i+1, j+1, retdest
%jumpi(modmul_check_loop)
// end of modmul_check_loop
// stack: n-1, i+1, j+1, retdest
%pop3
// stack: base_addr, n-1, i+1, j+1, retdest
%pop4
// stack: retdest
JUMP

View File

@ -12,49 +12,54 @@ global mul_bignum:
// stack: len, len, a_start_loc, b_start_loc, output_loc, retdest
ISZERO
%jumpi(len_zero)
DUP1
// stack: n=len, len, a_start_loc, bi=b_start_loc, output_cur=output_loc, retdest
%build_current_general_address_no_offset
DUP2
// stack: n=len, base_addr, len, a_start_loc, bi=b_start_loc, output_cur=output_loc, retdest
mul_loop:
// stack: n, len, a_start_loc, bi, output_cur, retdest
// stack: n, base_addr, len, a_start_loc, bi, output_cur, retdest
PUSH mul_addmul_return
// stack: mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest
DUP5
// stack: bi, mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest
%mload_current_general
// stack: b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b
DUP5
// stack: a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b
DUP8
// stack: output_loc, a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b
// stack: mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP6
// stack: len, output_loc, a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b
// stack: bi, mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP4 ADD // bi_addr
MLOAD_GENERAL
// stack: b[i], mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP6
// stack: a_start_loc, b[i], mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP9
// stack: output_loc, a_start_loc, b[i], mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP7
// stack: len, output_loc, a_start_loc, b[i], mul_addmul_return, n, base_addr, len, a_start_loc, bi, output_cur, retdest
%jump(addmul_bignum)
mul_addmul_return:
// stack: carry_limb, n, len, a_start_loc, bi, output_cur, retdest
DUP6
// stack: output_cur, carry_limb, n, len, a_start_loc, bi, output_cur, retdest
DUP4
// stack: len, output_cur, carry_limb, n, len, a_start_loc, bi, output_cur, retdest
// stack: carry_limb, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP7
// stack: output_cur, carry_limb, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP5
// stack: len, output_cur, carry_limb, n, base_addr, len, a_start_loc, bi, output_cur, retdest
ADD
// stack: output_cur + len, carry_limb, n, len, a_start_loc, bi, output_cur, retdest
%mstore_current_general
// stack: n, len, a_start_loc, bi, output_cur, retdest
// stack: output_cur + len, carry_limb, n, base_addr, len, a_start_loc, bi, output_cur, retdest
DUP4 ADD
%swap_mstore
// stack: n, base_addr, len, a_start_loc, bi, output_cur, retdest
%decrement
// stack: n-1, len, a_start_loc, bi, output_cur, retdest
SWAP3
%increment
SWAP3
// stack: n-1, len, a_start_loc, bi+1, output_cur, retdest
// stack: n-1, base_addr, len, a_start_loc, bi, output_cur, retdest
SWAP4
%increment
SWAP4
// stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest
// stack: n-1, base_addr, len, a_start_loc, bi+1, output_cur, retdest
SWAP5
%increment
SWAP5
// stack: n-1, base_addr, len, a_start_loc, bi+1, output_cur+1, retdest
DUP1
// stack: n-1, n-1, len, a_start_loc, bi+1, output_cur+1, retdest
// stack: n-1, n-1, base_addr, len, a_start_loc, bi+1, output_cur+1, retdest
%jumpi(mul_loop)
mul_end:
// stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest
%pop5
// stack: n-1, base_addr, len, a_start_loc, bi+1, output_cur+1, retdest
%pop6
// stack: retdest
JUMP

View File

@ -16,48 +16,54 @@ global shr_bignum:
// stack: start_loc + len, start_loc, retdest
%decrement
// stack: end_loc, start_loc, retdest
%stack (e) -> (e, 0)
// stack: i=end_loc, carry=0, start_loc, retdest
%build_current_general_address_no_offset
// stack: base_addr, end_loc, start_loc, retdest
%stack (addr, e) -> (e, addr, 0)
// stack: i=end_loc, base_addr, carry=0, start_loc, retdest
shr_loop:
// stack: i, carry, start_loc, retdest
// stack: i, base_addr, carry, start_loc, retdest
DUP1
// stack: i, i, carry, start_loc, retdest
%mload_current_general
// stack: a[i], i, carry, start_loc, retdest
// stack: i, i, base_addr, carry, start_loc, retdest
DUP3 ADD // addr_i
MLOAD_GENERAL
// stack: a[i], i, base_addr, carry, start_loc, retdest
DUP1
// stack: a[i], a[i], i, carry, start_loc, retdest
// stack: a[i], a[i], i, base_addr, carry, start_loc, retdest
%shr_const(1)
// stack: a[i] >> 1, a[i], i, carry, start_loc, retdest
// stack: a[i] >> 1, a[i], i, base_addr, carry, start_loc, retdest
SWAP1
// stack: a[i], a[i] >> 1, i, carry, start_loc, retdest
// stack: a[i], a[i] >> 1, i, base_addr, carry, start_loc, retdest
%mod_const(2)
// stack: new_carry = a[i] % 2, a[i] >> 1, i, carry, start_loc, retdest
SWAP3
// stack: carry, a[i] >> 1, i, new_carry, start_loc, retdest
// stack: new_carry = a[i] % 2, a[i] >> 1, i, base_addr, carry, start_loc, retdest
SWAP4
// stack: carry, a[i] >> 1, i, base_addr, new_carry, start_loc, retdest
%shl_const(127)
// stack: carry << 127, a[i] >> 1, i, new_carry, start_loc, retdest
// stack: carry << 127, a[i] >> 1, i, base_addr, new_carry, start_loc, retdest
ADD
// stack: carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest
// stack: carry << 127 | a[i] >> 1, i, base_addr, new_carry, start_loc, retdest
DUP2
// stack: i, carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest
%mstore_current_general
// stack: i, new_carry, start_loc, retdest
// stack: i, carry << 127 | a[i] >> 1, i, base_addr, new_carry, start_loc, retdest
DUP4 ADD // addr_i
%swap_mstore
// stack: i, base_addr, new_carry, start_loc, retdest
PUSH 1
DUP2
SUB
// stack: i-1, i, new_carry, start_loc, retdest
// stack: i-1, i, base_addr, new_carry, start_loc, retdest
SWAP1
// stack: i, i-1, new_carry, start_loc, retdest
DUP4
// stack: start_loc, i, i-1, new_carry, start_loc, retdest
// stack: i, i-1, base_addr, new_carry, start_loc, retdest
DUP5
// stack: start_loc, i, i-1, base_addr, new_carry, start_loc, retdest
EQ
// stack: i == start_loc, i-1, new_carry, start_loc, retdest
// stack: i == start_loc, i-1, base_addr, new_carry, start_loc, retdest
ISZERO
// stack: i != start_loc, i-1, new_carry, start_loc, retdest
// stack: i != start_loc, i-1, base_addr, new_carry, start_loc, retdest
%jumpi(shr_loop)
shr_end:
// stack: i, new_carry, start_loc, retdest
%pop3
// stack: i, base_addr, new_carry, start_loc, retdest
%pop4
// stack: retdest
JUMP

View File

@ -1,7 +1,7 @@
%macro memcpy_current_general
// stack: dst, src, len
// DST and SRC are offsets, for the same memory segment
GET_CONTEXT PUSH @SEGMENT_KERNEL_GENERAL %build_address_no_offset
%build_current_general_address_no_offset
%stack (addr_no_offset, dst, src, len) -> (addr_no_offset, src, addr_no_offset, dst, len, %%after)
ADD
// stack: SRC, addr_no_offset, dst, len, %%after
@ -14,7 +14,7 @@
%macro clear_current_general
// stack: dst, len
GET_CONTEXT PUSH @SEGMENT_KERNEL_GENERAL %build_address
%build_current_general_address
%stack (DST, len) -> (DST, len, %%after)
%jump(memset)
%%after:

View File

@ -2,11 +2,7 @@
// It is ready to be used, i.e. already containing the current context
// and SEGMENT_KERNEL_GENERAL.
%macro blake2_hash_value_addr
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment
GET_CONTEXT
// stack: context, segment
%build_address_no_offset
%build_current_general_address_no_offset
DUP1
MLOAD_GENERAL
// stack: num_blocks, addr

View File

@ -4,9 +4,7 @@
// stack: num_blocks
%mul_const(320)
%add_const(2)
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
%build_current_general_address
%endmacro
global sha2_compression:

View File

@ -1,8 +1,6 @@
global sha2:
// stack: virt, num_bytes, retdest
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
%build_current_general_address
// stack: addr, num_bytes, retdest
DUP1 SWAP2
// stack: num_bytes, addr, addr, retdest

View File

@ -3,9 +3,7 @@
// stack: num_blocks
%mul_const(64)
%add_const(2)
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
%build_current_general_address
%endmacro
// Precondition: stack contains address of one message block, followed by output address
@ -188,9 +186,7 @@ global sha2_gen_all_message_schedules:
// stack: num_blocks, output_addr, output_addr, retdest
PUSH 1
// stack: cur_offset = 1, counter = num_blocks, output_addr, output_addr, retdest
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
%build_current_general_address
// stack: cur_addr, counter, output_addr, output_addr, retdest
gen_all_message_schedules_loop:
// stack: cur_addr, counter, cur_output_addr, output_addr, retdest

View File

@ -1,8 +1,6 @@
%macro sha2_write_length
// stack: last_addr_offset, length
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
%build_current_general_address
SWAP1
// stack: length, last_addr
DUP1

View File

@ -127,9 +127,7 @@
// Load a single value from the kernel general memory, in the current context (not the kernel's context).
%macro mload_current_general_no_offset
// stack:
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address_no_offset
%build_current_general_address_no_offset
MLOAD_GENERAL
// stack: value
%endmacro
@ -137,11 +135,7 @@
// Load a big-endian u32 from kernel general memory in the current context.
%macro mload_current_general_u32
// stack: offset
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset
GET_CONTEXT
// stack: context, segment, offset
%build_address
%build_current_general_address
%mload_u32
// stack: value
%endmacro
@ -149,11 +143,7 @@
// Load a little-endian u32 from kernel general memory in the current context.
%macro mload_current_general_u32_LE
// stack: offset
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset
GET_CONTEXT
// stack: context, segment, offset
%build_address
%build_current_general_address
%mload_u32_LE
// stack: value
%endmacro
@ -161,11 +151,7 @@
// Load a little-endian u64 from kernel general memory in the current context.
%macro mload_current_general_u64_LE
// stack: offset
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset
GET_CONTEXT
// stack: context, segment, offset
%build_address
%build_current_general_address
%mload_u64_LE
// stack: value
%endmacro
@ -173,11 +159,7 @@
// Load a u256 from kernel general memory in the current context.
%macro mload_current_general_u256
// stack: offset
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset
GET_CONTEXT
// stack: context, segment, offset
%build_address
%build_current_general_address
%mload_u256
// stack: value
%endmacro
@ -185,11 +167,7 @@
// Store a single value to kernel general memory in the current context.
%macro mstore_current_general
// stack: offset, value
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset, value
GET_CONTEXT
// stack: context, segment, offset, value
%build_address
%build_current_general_address
SWAP1
MSTORE_GENERAL
// stack: (empty)
@ -198,11 +176,7 @@
// Store a single value to kernel general memory in the current context.
%macro mstore_current_general_no_offset
// stack: value
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, value
GET_CONTEXT
// stack: context, segment, value
%build_address_no_offset
%build_current_general_address_no_offset
SWAP1
MSTORE_GENERAL
// stack: (empty)
@ -219,11 +193,7 @@
// Store a big-endian u32 to kernel general memory in the current context.
%macro mstore_current_general_u32
// stack: offset, value
PUSH @SEGMENT_KERNEL_GENERAL
// stack: segment, offset, value
GET_CONTEXT
// stack: context, segment, offset, value
%build_address
%build_current_general_address
%mstore_u32
// stack: (empty)
%endmacro

View File

@ -440,6 +440,22 @@
// stack: addr
%endmacro
%macro build_current_general_address
// stack: offset
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address
// stack: addr
%endmacro
%macro build_current_general_address_no_offset
// stack:
PUSH @SEGMENT_KERNEL_GENERAL
GET_CONTEXT
%build_address_no_offset
// stack: addr (offset == 0)
%endmacro
%macro build_kernel_address
// stack: seg, off
ADD

View File

@ -169,10 +169,10 @@ impl<F: Field> GenerationState<F> {
// Subsequent calls return one limb at a time, in order (first remainder and then quotient).
fn run_bignum_modmul(&mut self) -> Result<U256, ProgramError> {
if self.bignum_modmul_result_limbs.is_empty() {
let len = stack_peek(self, 1).map(u256_to_usize)??;
let a_start_loc = stack_peek(self, 2).map(u256_to_usize)??;
let b_start_loc = stack_peek(self, 3).map(u256_to_usize)??;
let m_start_loc = stack_peek(self, 4).map(u256_to_usize)??;
let len = stack_peek(self, 2).map(u256_to_usize)??;
let a_start_loc = stack_peek(self, 3).map(u256_to_usize)??;
let b_start_loc = stack_peek(self, 4).map(u256_to_usize)??;
let m_start_loc = stack_peek(self, 5).map(u256_to_usize)??;
let (remainder, quotient) =
self.bignum_modmul(len, a_start_loc, b_start_loc, m_start_loc);