using memory

This commit is contained in:
Nicholas Ward 2022-07-14 14:58:28 -07:00
parent 4378ff0fc2
commit 2c7b60e286
2 changed files with 90 additions and 426 deletions

View File

@ -41,48 +41,63 @@ case1:
case2:
JUMPDEST
swap2
%jump(swapn_end)
case3:
JUMPDEST
swap3
%jump(swapn_end)
case4:
JUMPDEST
swap4
%jump(swapn_end)
case5:
JUMPDEST
swap5
%jump(swapn_end)
case6:
JUMPDEST
swap6
%jump(swapn_end)
case7:
JUMPDEST
swap7
%jump(swapn_end)
case8:
JUMPDEST
swap8
%jump(swapn_end)
case9:
JUMPDEST
swap9
%jump(swapn_end)
case10:
JUMPDEST
swap10
%jump(swapn_end)
case11:
JUMPDEST
swap11
%jump(swapn_end)
case12:
JUMPDEST
swap12
%jump(swapn_end)
case13:
JUMPDEST
swap13
%jump(swapn_end)
case14:
JUMPDEST
swap14
%jump(swapn_end)
case15:
JUMPDEST
swap15
%jump(swapn_end)
case16:
JUMPDEST
swap16
%jump(swapn_end)
swapn_end:
JUMPDEST

View File

@ -19,441 +19,90 @@ count_bits_loop:
pop
// stack: bits
// Appends a 1 to the end of the u256 at the top of the stack.
global append_1:
dup
count_bits
%eq(256)
%jumpi(append_if256)
%jump(append_else)
append_if256:
push 1
swap1
%jump(append_end)
append_else:
push 2
mul
push 1
add
append_end:
global sha2_append_1:
global sha2_store:
// stack: num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
// (assume num_u256s <= 16)
dup
dup1
// stack: num_u256s, num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
dup
// stack: num_u256s, num_u256s, num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
%increment
// stack: num_u256s+1, num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
swapn
// stack: x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s
dup
// stack: x[num_u256s-1], x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s
%count_bits
// stack: num_bits, x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s
%eq(256)
%jumpi(append_if256)
%jump(append_else)
append_if256:
// TODO: use kernel memory, and start address not at 0
push 0
// stack: addr=0, num_u256s, num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
mstore
// stack: num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
push 1
// stack: 1, x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s
dup2
// stack: num_u256s, 1, x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s
push 3
add
// stack: num_u256s+3, 1, x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s, []
swapn
// stack: [], x[num_u256s-1], num_u256s, x[0], x[1], x[2], ... , x[num_u256s-2], num_u256s,
%jump(append_continue)
append_else:
append_continue:
dup
// stack: addr=1, counter=num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
sha2_store_loop:
JUMPDEST
// stack: addr, counter, x[num_u256s-counter], ... , x[num_u256s-1]
dup1
// stack: addr, addr, counter, x[num_u256s-counter], ... , x[num_u256s-1]
swap3
// stack: x[num_u256s-counter], addr, counter, addr, ... , x[num_u256s-1]
swap1
// stack: addr, x[num_u256s-counter], counter, addr, ... , x[num_u256s-1]
mstore
// stack: counter, addr, ... , x[num_u256s-1]
%decrement
// stack: counter-1, addr, ... , x[num_u256s-1]
iszero
%jumpi(sha2_store_end)
swap1
// stack: addr, counter-1, ... , x[num_u256s-1]
%increment
// stack: addr+1, counter-1, ... , x[num_u256s-1]
%jump(sha2_store_loop)
sha2_store_end:
JUMPDEST
global sha2_pad:
// stack: num_u256s, x[0], x[1], x[2], ... , x[num_u256s-1]
%jumpi()
append 1:
if length of last = 256
increment length; add new value of 10000000..0
stick 1 on the end (last one:)
if length even:
pad last one to
if length odd:
// stack: num_blocks, block[0][0], block[0][1], ..., block[num_blocks-1][3]
// #define K0 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
// BN254 elliptic curve addition.
// Uses the standard affine addition formula.
global ec_add:
// Uncomment for test inputs.
// PUSH 0xdeadbeef
// PUSH 2
// PUSH 1
// PUSH 0x1bf9384aa3f0b3ad763aee81940cacdde1af71617c06f46e11510f14f3d5d121
// PUSH 0xe7313274bb29566ff0c8220eb9841de1d96c2923c6a4028f7dd3c6a14cee770
// TODO: use kernel memory, and start address not at 0
push 0
mload
// stack: num_u256s
mload
// stack: x[num_u256s-1]
dup1
// stack: x[num_u256s-1], x[num_u256s-1]
%count_bits
// stack: num_bits, x[num_u256s-1]
%eq(256)
%jumpi(pad_if256)
%jump(pad_else)
pad_if256:
JUMPDEST
// stack: x0, y0, x1, y1, retdest
// Check if points are valid BN254 points.
DUP2
// stack: y0, x0, y0, x1, y1, retdest
DUP2
// stack: x0, y0, x0, y0, x1, y1, retdest
%ec_check
// stack: isValid(x0, y0), x0, y0, x1, y1, retdest
DUP5
// stack: x1, isValid(x0, y0), x0, y0, x1, y1, retdest
DUP5
// stack: x1, y1, isValid(x0, y0), x0, y0, x1, y1, retdest
%ec_check
// stack: isValid(x1, y1), isValid(x0, y0), x0, y0, x1, y1, retdest
AND
// stack: isValid(x1, y1) & isValid(x0, y0), x0, y0, x1, y1, retdest
%jumpi(ec_add_valid_points)
// stack: x0, y0, x1, y1, retdest
// Otherwise return
%pop4
// stack: retdest
%ec_invalid_input
// BN254 elliptic curve addition.
// Assumption: (x0,y0) and (x1,y1) are valid points.
global ec_add_valid_points:
JUMPDEST
// stack: x0, y0, x1, y1, retdest
// Check if the first point is the identity.
DUP2
// stack: y0, x0, y0, x1, y1, retdest
DUP2
// stack: x0, y0, x0, y0, x1, y1, retdest
%ec_isidentity
// stack: (x0,y0)==(0,0), x0, y0, x1, y1, retdest
%jumpi(ec_add_first_zero)
// stack: x0, y0, x1, y1, retdest
// Check if the first point is the identity.
DUP4
// stack: y1, x0, y0, x1, y1, retdest
DUP4
// stack: x1, y1, x0, y0, x1, y1, retdest
%ec_isidentity
// stack: (x1,y1)==(0,0), x0, y0, x1, y1, retdest
%jumpi(ec_add_snd_zero)
// stack: x0, y0, x1, y1, retdest
// Check if both points have the same x-coordinate.
DUP3
// stack: x1, x0, y0, x1, y1, retdest
DUP2
// stack: x0, x1, x0, y0, x1, y1, retdest
EQ
// stack: x0 == x1, x0, y0, x1, y1, retdest
%jumpi(ec_add_equal_first_coord)
// stack: x0, y0, x1, y1, retdest
// Otherwise, we can use the standard formula.
// Compute lambda = (y0 - y1)/(x0 - x1)
DUP4
// stack: y1, x0, y0, x1, y1, retdest
DUP3
// stack: y0, y1, x0, y0, x1, y1, retdest
%submod
// stack: y0 - y1, x0, y0, x1, y1, retdest
DUP4
// stack: x1, y0 - y1, x0, y0, x1, y1, retdest
DUP3
// stack: x0, x1, y0 - y1, x0, y0, x1, y1, retdest
%submod
// stack: x0 - x1, y0 - y1, x0, y0, x1, y1, retdest
%moddiv
// stack: lambda, x0, y0, x1, y1, retdest
%jump(ec_add_valid_points_with_lambda)
// BN254 elliptic curve addition.
// Assumption: (x0,y0) == (0,0)
ec_add_first_zero:
JUMPDEST
// stack: x0, y0, x1, y1, retdest
// Just return (x1,y1)
// stack: num_bits, x[num_u256s-1]
%pop2
// stack: x1, y1, retdest
SWAP1
// stack: y1, x1, retdest
SWAP2
// stack: retdest, x1, y1
JUMP
// BN254 elliptic curve addition.
// Assumption: (x1,y1) == (0,0)
ec_add_snd_zero:
push 0
mload
// stack: num_u256s
%increment
// stack: num_u256s+1
dup1
// stack: num_u256s+1, num_u256s+1
push 0
mstore
// stack: num_u256s+1
push 1
// stack: 1, num_u256s+1
swap1
// stack: num_u256s+1, 1
mstore
%jump(pad_end)
pad_else:
JUMPDEST
// stack: x0, y0, x1, y1, retdest
// Just return (x1,y1)
SWAP2
// stack: x1, y0, x0, y1, retdest
POP
// stack: y0, x0, y1, retdest
SWAP2
// stack: y1, x0, y0, retdest
POP
// stack: x0, y0, retdest
SWAP1
// stack: y0, x0, retdest
SWAP2
// stack: retdest, x0, y0
JUMP
// BN254 elliptic curve addition.
// Assumption: lambda = (y0 - y1)/(x0 - x1)
ec_add_valid_points_with_lambda:
// stack: num_bits, x[num_u256s-1]
pop
// stack: x[num_u256s-1]
push 2
mul
// stack: 2*x[num_u256s-1]
%increment
// stack: 2*x[num_u256s-1]+1
push 0
mload
// stack: num_u256s, 2*x[num_u256s-1]+1
mstore
pad_end:
JUMPDEST
// stack: lambda, x0, y0, x1, y1, retdest
// Compute x2 = lambda^2 - x1 - x0
DUP2
// stack: x0, lambda, x0, y0, x1, y1, retdest
DUP5
// stack: x1, x0, lambda, x0, y0, x1, y1, retdest
%bn_base
// stack: N, x1, x0, lambda, x0, y0, x1, y1, retdest
DUP4
// stack: lambda, N, x1, x0, lambda, x0, y0, x1, y1, retdest
DUP1
// stack: lambda, lambda, N, x1, x0, lambda, x0, y0, x1, y1, retdest
MULMOD
// stack: lambda^2, x1, x0, lambda, x0, y0, x1, y1, retdest
%submod
// stack: lambda^2 - x1, x0, lambda, x0, y0, x1, y1, retdest
%submod
// stack: x2, lambda, x0, y0, x1, y1, retdest
// Compute y2 = lambda*(x1 - x2) - y1
%bn_base
// stack: N, x2, lambda, x0, y0, x1, y1, retdest
DUP2
// stack: x2, N, x2, lambda, x0, y0, x1, y1, retdest
DUP7
// stack: x1, x2, N, x2, lambda, x0, y0, x1, y1, retdest
%submod
// stack: x1 - x2, N, x2, lambda, x0, y0, x1, y1, retdest
DUP4
// stack: lambda, x1 - x2, N, x2, lambda, x0, y0, x1, y1, retdest
MULMOD
// stack: lambda * (x1 - x2), x2, lambda, x0, y0, x1, y1, retdest
DUP7
// stack: y1, lambda * (x1 - x2), x2, lambda, x0, y0, x1, y1, retdest
SWAP1
// stack: lambda * (x1 - x2), y1, x2, lambda, x0, y0, x1, y1, retdest
%submod
// stack: y2, x2, lambda, x0, y0, x1, y1, retdest
// Return x2,y2
SWAP5
// stack: x1, x2, lambda, x0, y0, y2, y1, retdest
POP
// stack: x2, lambda, x0, y0, y2, y1, retdest
SWAP5
// stack: y1, lambda, x0, y0, y2, x2, retdest
%pop4
// stack: y2, x2, retdest
SWAP2
// stack: retdest, x2, y2
JUMP
// BN254 elliptic curve addition.
// Assumption: (x0,y0) and (x1,y1) are valid points and x0 == x1
ec_add_equal_first_coord:
JUMPDEST
// stack: x0, y0, x1, y1, retdest with x0 == x1
// Check if the points are equal
DUP2
// stack: y0, x0, y0, x1, y1, retdest
DUP5
// stack: y1, y0, x0, y0, x1, y1, retdest
EQ
// stack: y1 == y0, x0, y0, x1, y1, retdest
%jumpi(ec_add_equal_points)
// stack: x0, y0, x1, y1, retdest
// Otherwise, one is the negation of the other so we can return (0,0).
%pop4
// stack: retdest
PUSH 0
// stack: 0, retdest
PUSH 0
// stack: 0, 0, retdest
SWAP2
// stack: retdest, 0, 0
JUMP
// BN254 elliptic curve addition.
// Assumption: x0 == x1 and y0 == y1
// Standard doubling formula.
ec_add_equal_points:
JUMPDEST
// stack: x0, y0, x1, y1, retdest
// Compute lambda = 3/2 * x0^2 / y0
%bn_base
// stack: N, x0, y0, x1, y1, retdest
%bn_base
// stack: N, N, x0, y0, x1, y1, retdest
DUP3
// stack: x0, N, N, x0, y0, x1, y1, retdest
DUP1
// stack: x0, x0, N, N, x0, y0, x1, y1, retdest
MULMOD
// stack: x0^2, N, x0, y0, x1, y1, retdest with
PUSH 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea5 // 3/2 in the base field
// stack: 3/2, x0^2, N, x0, y0, x1, y1, retdest
MULMOD
// stack: 3/2 * x0^2, x0, y0, x1, y1, retdest
DUP3
// stack: y0, 3/2 * x0^2, x0, y0, x1, y1, retdest
%moddiv
// stack: lambda, x0, y0, x1, y1, retdest
%jump(ec_add_valid_points_with_lambda)
// BN254 elliptic curve doubling.
// Assumption: (x0,y0) is a valid point.
// Standard doubling formula.
global ec_double:
JUMPDEST
// stack: x0, y0, retdest
DUP2
// stack: y0, x0, y0, retdest
DUP2
// stack: x0, y0, x0, y0, retdest
%jump(ec_add_equal_points)
// Push the order of the BN254 base field.
%macro bn_base
PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
%endmacro
// Assumption: x, y < N and 2N < 2^256.
// Note: Doesn't hold for Secp256k1 base field.
%macro submod
// stack: x, y
%bn_base
// stack: N, x, y
ADD
// stack: N + x, y // Doesn't overflow since 2N < 2^256
SUB
// stack: N + x - y // Doesn't underflow since y < N
%bn_base
// stack: N, N + x - y
SWAP1
// stack: N + x - y, N
MOD
// stack: (N + x - y) % N = (x-y) % N
%endmacro
// Check if (x,y) is a valid curve point.
// Puts y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0) on top of the stack.
%macro ec_check
// stack: x, y
%bn_base
// stack: N, x, y
DUP2
// stack: x, N, x, y
LT
// stack: x < N, x, y
%bn_base
// stack: N, x < N, x, y
DUP4
// stack: y, N, x < N, x, y
LT
// stack: y < N, x < N, x, y
AND
// stack: (y < N) & (x < N), x, y
SWAP2
// stack: y, x, (y < N) & (x < N), x
SWAP1
// stack: x, y, (y < N) & (x < N)
%bn_base
// stack: N, x, y, b
%bn_base
// stack: N, N, x, y, b
DUP3
// stack: x, N, N, x, y, b
%bn_base
// stack: N, x, N, N, x, y, b
DUP2
// stack: x, N, x, N, N, x, y, b
DUP1
// stack: x, x, N, x, N, N, x, y, b
MULMOD
// stack: x^2 % N, x, N, N, x, y, b
MULMOD
// stack: x^3 % N, N, x, y, b
PUSH 3
// stack: 3, x^3 % N, N, x, y, b
ADDMOD
// stack: (x^3 + 3) % N, x, y, b
DUP3
// stack: y, (x^3 + 3) % N, x, y, b
%bn_base
// stack: N, y, (x^3 + 3) % N, x, y, b
SWAP1
// stack: y, N, (x^3 + 3) % N, x, y, b
DUP1
// stack: y, y, N, (x^3 + 3) % N, x, y, b
MULMOD
// stack: y^2 % N, (x^3 + 3) % N, x, y, b
EQ
// stack: y^2 % N == (x^3 + 3) % N, x, y, b
SWAP2
// stack: y, x, y^2 % N == (x^3 + 3) % N, b
%ec_isidentity
// stack: (x,y)==(0,0), y^2 % N == (x^3 + 3) % N, b
SWAP2
// stack: b, y^2 % N == (x^3 + 3) % N, (x,y)==(0,0)
AND
// stack: y^2 % N == (x^3 + 3) % N & (x < N) & (y < N), (x,y)==(0,0)
OR
// stack: y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0)
%endmacro
// Check if (x,y)==(0,0)
%macro ec_isidentity
// stack: x, y
OR
// stack: x | y
ISZERO
// stack: (x,y) == (0,0)
%endmacro
// Return (u256::MAX, u256::MAX) which is used to indicate the input was invalid.
%macro ec_invalid_input
// stack: retdest
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// stack: u256::MAX, retdest
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// stack: u256::MAX, u256::MAX, retdest
SWAP2
// stack: retdest, u256::MAX, u256::MAX
JUMP
%endmacro