diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 250c69cc..1df24c6e 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -27,18 +27,16 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_mul.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/glv.asm"), include_str!("asm/curve/bn254/curve_arithmetic/invariant_exponent.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/msm.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/precomputation.asm"), include_str!("asm/curve/bn254/curve_arithmetic/tate_pairing.asm"), include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_6_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_12_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"), include_str!("asm/curve/bn254/field_arithmetic/util.asm"), - include_str!("asm/curve/bn254/curve_add.asm"), - include_str!("asm/curve/bn254/curve_mul.asm"), - include_str!("asm/curve/bn254/glv.asm"), - include_str!("asm/curve/bn254/msm.asm"), - include_str!("asm/curve/bn254/precomputation.asm"), include_str!("asm/curve/common.asm"), include_str!("asm/curve/secp256k1/curve_add.asm"), include_str!("asm/curve/secp256k1/ecrecover.asm"), diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_add.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_add.asm deleted file mode 100644 index 3e917120..00000000 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_add.asm +++ /dev/null @@ -1,305 +0,0 @@ -// #define N 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 // BN254 base field order - -// BN254 elliptic curve addition. -// Uses the standard affine addition formula. -global bn_add: - // Uncomment for test inputs. - // PUSH 0xdeadbeef - // PUSH 2 - // PUSH 1 - // PUSH 0x1bf9384aa3f0b3ad763aee81940cacdde1af71617c06f46e11510f14f3d5d121 - // PUSH 0xe7313274bb29566ff0c8220eb9841de1d96c2923c6a4028f7dd3c6a14cee770 - // 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 - %bn_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 - %bn_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(bn_add_valid_points) - // stack: x0, y0, x1, y1, retdest - - // Otherwise return - %pop4 - // stack: retdest - %bn_invalid_input - -// BN254 elliptic curve addition. -// Assumption: (x0,y0) and (x1,y1) are valid points. -global bn_add_valid_points: - // 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(bn_add_first_zero) - // stack: x0, y0, x1, y1, retdest - - // Check if the second 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(bn_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(bn_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(bn_add_valid_points_with_lambda) - -// BN254 elliptic curve addition. -// Assumption: (x0,y0) == (0,0) -bn_add_first_zero: - // stack: x0, y0, x1, y1, retdest - // Just return (x1,y1) - %stack (x0, y0, x1, y1, retdest) -> (retdest, x1, y1) - JUMP - -// BN254 elliptic curve addition. -// Assumption: (x1,y1) == (0,0) -bn_add_snd_zero: - // stack: x0, y0, x1, y1, retdest - - // Just return (x0,y0) - %stack (x0, y0, x1, y1, retdest) -> (retdest, x0, y0) - JUMP - -// BN254 elliptic curve addition. -// Assumption: lambda = (y0 - y1)/(x0 - x1) -bn_add_valid_points_with_lambda: - // 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 - %stack (y2, x2, lambda, x0, y0, x1, y1, retdest) -> (retdest, x2, y2) - JUMP - -// BN254 elliptic curve addition. -// Assumption: (x0,y0) and (x1,y1) are valid points and x0 == x1 -bn_add_equal_first_coord: - // 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(bn_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. -bn_add_equal_points: - // 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(bn_add_valid_points_with_lambda) - -// BN254 elliptic curve doubling. -// Assumption: (x0,y0) is a valid point. -// Standard doubling formula. -global bn_double: - // stack: x, y, retdest - DUP2 DUP2 %ec_isidentity - // stack: (x,y)==(0,0), x, y, retdest - %jumpi(ec_double_retself) - DUP2 DUP2 - // stack: x, y, x, y, retdest - %jump(bn_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 bn_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 - %stack (b, x, y) -> (x, x, @BN_BASE, x, @BN_BASE, @BN_BASE, x, y, b) - // 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 - -// Return (u256::MAX, u256::MAX) which is used to indicate the input was invalid. -%macro bn_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 \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm index 0ac947da..e85838ea 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm @@ -1,81 +1,95 @@ -// BN254 elliptic curve addition via the standard affine addition formula. +// #define N 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 // BN254 base field order -global ec_add: - // stack: x0, y0, x1, y1, retdest +// BN254 elliptic curve addition. +// Uses the standard affine addition formula. +global bn_add: + // Uncomment for test inputs. + // PUSH 0xdeadbeef + // PUSH 2 + // PUSH 1 + // PUSH 0x1bf9384aa3f0b3ad763aee81940cacdde1af71617c06f46e11510f14f3d5d121 + // PUSH 0xe7313274bb29566ff0c8220eb9841de1d96c2923c6a4028f7dd3c6a14cee770 + // stack: x0, y0, x1, y1, retdest // Check if points are valid BN254 points. DUP2 - DUP2 - // stack: x0, y0, x0, y0, x1, y1, retdest - %ec_check - // stack: isValid(x0, y0), x0, y0, x1, y1, retdest + // stack: y0, x0, y0, x1, y1, retdest + DUP2 + // stack: x0, y0, x0, y0, x1, y1, retdest + %bn_check + // stack: isValid(x0, y0), x0, y0, x1, y1, retdest DUP5 - 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 + // stack: x1, isValid(x0, y0), x0, y0, x1, y1, retdest + DUP5 + // stack: x1, y1, isValid(x0, y0), x0, y0, x1, y1, retdest + %bn_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 + %jumpi(bn_add_valid_points) + // stack: x0, y0, x1, y1, retdest // Otherwise return %pop4 // stack: retdest - %ec_invalid_input + %bn_invalid_input // BN254 elliptic curve addition. // Assumption: (x0,y0) and (x1,y1) are valid points. -global ec_add_valid_points: - // stack: x0, y0, x1, y1, retdest +global bn_add_valid_points: + // 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 + // stack: x0, y0, x0, y0, x1, y1, retdest %ec_isidentity - // stack: (0,0)==(x0,y0), x0, y0, x1, y1, retdest - %jumpi(ec_add_fst_zero) - // stack: x0, y0, x1, y1, retdest + // stack: (x0,y0)==(0,0), x0, y0, x1, y1, retdest + %jumpi(bn_add_first_zero) + // stack: x0, y0, x1, y1, retdest // Check if the second point is the identity. DUP4 - DUP4 - // stack: x1,y1 , x0, y0, x1, y1, retdest + // stack: y1, x0, y0, x1, y1, retdest + DUP4 + // stack: x1, y1, x0, y0, x1, y1, retdest %ec_isidentity - // stack: (0,0)==(x1,y1), x0, y0, x1, y1, retdest - %jumpi(ec_add_snd_zero) - // stack: x0, y0, x1, y1, retdest + // stack: (x1,y1)==(0,0), x0, y0, x1, y1, retdest + %jumpi(bn_add_snd_zero) + // stack: x0, y0, x1, y1, retdest // Check if both points have the same x-coordinate. DUP3 - DUP2 - // stack: x0 , x1, x0, y0, x1, y1, retdest + // 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 == x1, x0, y0, x1, y1, retdest + %jumpi(bn_add_equal_first_coord) + // stack: x0, y0, x1, y1, retdest - - // 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 - SUBFP254 - // stack: y0 - y1, x0, y0, x1, y1, retdest + // 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 - SUBFP254 + // stack: x0, x1, y0 - y1, x0, y0, x1, y1, retdest + %submod // stack: x0 - x1, y0 - y1, x0, y0, x1, y1, retdest - %divfp254 - // stack: lambda, x0, y0, x1, y1, retdest - %jump(ec_add_valid_points_with_lambda) + %divr_fp254 + // stack: lambda, x0, y0, x1, y1, retdest + %jump(bn_add_valid_points_with_lambda) // BN254 elliptic curve addition. // Assumption: (x0,y0) == (0,0) -ec_add_fst_zero: +bn_add_first_zero: // stack: x0, y0, x1, y1, retdest // Just return (x1,y1) %stack (x0, y0, x1, y1, retdest) -> (retdest, x1, y1) @@ -83,48 +97,55 @@ ec_add_fst_zero: // BN254 elliptic curve addition. // Assumption: (x1,y1) == (0,0) -ec_add_snd_zero: +bn_add_snd_zero: // stack: x0, y0, x1, y1, retdest + // Just return (x0,y0) %stack (x0, y0, x1, y1, retdest) -> (retdest, x0, y0) JUMP // BN254 elliptic curve addition. // Assumption: lambda = (y0 - y1)/(x0 - x1) -ec_add_valid_points_with_lambda: - // stack: lambda, x0, y0, x1, y1, retdest +bn_add_valid_points_with_lambda: + // 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 - DUP3 - // stack: lambda , x1, x0, lambda, x0, y0, x1, y1, retdest + // 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 - MULFP254 - // stack: lambda^2 , x1, x0, lambda, x0, y0, x1, y1, retdest - SUBFP254 - // stack: lambda^2 - x1, x0, lambda, x0, y0, x1, y1, retdest - SUBFP254 - // stack: x2, lambda, x0, y0, x1, y1, retdest + // 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 - DUP1 - // stack: x2 , x2, lambda, x0, y0, x1, y1, retdest - DUP6 - // stack: x1 , x2 , x2, lambda, x0, y0, x1, y1, retdest - SUBFP254 - // stack: x1 - x2 , x2, lambda, x0, y0, x1, y1, retdest - DUP3 - // stack: lambda , x1 - x2 , x2, lambda, x0, y0, x1, y1, retdest - MULFP254 - // stack: lambda * (x1 - x2), x2, lambda, x0, y0, x1, y1, retdest + %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 - SUBFP254 - // stack: y2, x2, lambda, x0, y0, x1, y1, retdest + %submod + // stack: y2, x2, lambda, x0, y0, x1, y1, retdest // Return x2,y2 %stack (y2, x2, lambda, x0, y0, x1, y1, retdest) -> (retdest, x2, y2) @@ -132,22 +153,25 @@ ec_add_valid_points_with_lambda: // BN254 elliptic curve addition. // Assumption: (x0,y0) and (x1,y1) are valid points and x0 == x1 -ec_add_equal_first_coord: - // stack: x0, y0, x1, y1, retdest with x0 == x1 +bn_add_equal_first_coord: + // 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 + // 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 + %jumpi(bn_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 PUSH 0 + // stack: retdest + PUSH 0 + // stack: 0, retdest + PUSH 0 // stack: 0, 0, retdest SWAP2 // stack: retdest, 0, 0 @@ -157,118 +181,125 @@ ec_add_equal_first_coord: // BN254 elliptic curve addition. // Assumption: x0 == x1 and y0 == y1 // Standard doubling formula. -ec_add_equal_points: - // stack: x0, y0, x1, y1, retdest - // Compute lambda = 3/2 * x0^2 / y0 +bn_add_equal_points: + // 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, y0, x1, y1, retdest - DUP1 - MULFP254 - // stack: x0^2, x0, y0, x1, y1, retdest - %bn_3_over_2 - // stack: 3/2 , x0^2, x0, y0, x1, y1, retdest - MULFP254 - // stack: 3/2 * x0^2, x0, y0, x1, y1, retdest + // 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 - %divfp254 - // stack: lambda, x0, y0, x1, y1, retdest - %jump(ec_add_valid_points_with_lambda) + %divr_fp254 + // stack: lambda, x0, y0, x1, y1, retdest + %jump(bn_add_valid_points_with_lambda) // BN254 elliptic curve doubling. // Assumption: (x0,y0) is a valid point. // Standard doubling formula. -global ec_double: - // stack: x0, y0, retdest - DUP2 - DUP2 - // stack: x0, y0, x0, y0, retdest - %jump(ec_add_equal_points) +global bn_double: + // stack: x, y, retdest + DUP2 DUP2 %ec_isidentity + // stack: (x,y)==(0,0), x, y, retdest + %jumpi(ec_double_retself) + DUP2 DUP2 + // stack: x, y, x, y, retdest + %jump(bn_add_equal_points) // Push the order of the BN254 base field. %macro bn_base PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 %endmacro -%macro bn_3_over_2 - // 3/2 in the base field - PUSH 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea5 +// 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. -// Returns range & curve || is_identity -// where -// range = (x < N) & (y < N) -// curve = y^2 == (x^3 + 3) -// ident = (x,y) == (0,0) - -%macro ec_check - // stack: x, y - DUP1 - // stack: x, x, y +// Puts y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0) on top of the stack. +%macro bn_check + // stack: x, y %bn_base - // stack: N , x, x, y - DUP1 - // stack: N, N , x, x, y - DUP5 - // stack: y , N, N , x, x, y - LT - // stack: y < N, N , x, x, y - SWAP2 - // stack: x , N, y < N, x, y - LT - // stack: x < N, y < N, x, y - AND - // stack: range, x, y - SWAP2 - // stack: y, x, range - DUP2 - // stack: x , y, x, range - DUP1 - DUP1 - MULFP254 - MULFP254 - // stack: x^3, y, x, range - PUSH 3 - ADDFP254 - // stack: 3 + x^3, y, x, range + // stack: N, x, y DUP2 - // stack: y , 3 + x^3, y, x, range - DUP1 - MULFP254 - // stack: y^2, 3 + x^3, y, x, range - EQ - // stack: curve, y, x, range - SWAP2 - // stack: x, y, curve, range - %ec_isidentity - // stack: ident , curve, range - SWAP2 - // stack: range , curve, ident + // 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: range & curve, ident + // stack: (y < N) & (x < N), x, y + %stack (b, x, y) -> (x, x, @BN_BASE, x, @BN_BASE, @BN_BASE, x, y, b) + // 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: is_valid -%endmacro - -// Check if (x,y)==(0,0) -%macro ec_isidentity - // stack: x , y - OR - // stack: x | y - ISZERO - // stack: (x,y) == (0,0) + // stack: y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0) %endmacro // Return (u256::MAX, u256::MAX) which is used to indicate the input was invalid. -%macro ec_invalid_input +%macro bn_invalid_input // stack: retdest PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // stack: u256::MAX, retdest - DUP1 + PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // stack: u256::MAX, u256::MAX, retdest SWAP2 // stack: retdest, u256::MAX, u256::MAX JUMP -%endmacro +%endmacro \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_mul.asm index 843053e9..ecbb3de0 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_mul.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_mul.asm @@ -1,90 +1,41 @@ // BN254 elliptic curve scalar multiplication. -// Recursive implementation, same algorithm as in `exp.asm`. -global ec_mul: - // stack: x, y, s, retdest +// Uses GLV, wNAF with w=5, and a MSM algorithm. +global bn_mul: + // stack: x, y, s, retdest DUP2 - // stack: y , x, y, s, retdest + // stack: y, x, y, s, retdest DUP2 - // stack: x,y , x, y, s, retdest + // stack: x, y, x, y, s, retdest %ec_isidentity - // stack: (0,0)==(x,y), x, y, s, retdest + // stack: (x,y)==(0,0), x, y, s, retdest %jumpi(ret_zero_ec_mul) - // stack: x, y, s, retdest + // stack: x, y, s, retdest DUP2 - // stack: y, x, y, s, retdest + // stack: y, x, y, s, retdest DUP2 - // stack: x, y, x, y, s, retdest - %ec_check + // stack: x, y, x, y, s, retdest + %bn_check // stack: isValid(x, y), x, y, s, retdest - %jumpi(ec_mul_valid_point) - // stack: x, y, s, retdest + %jumpi(bn_mul_valid_point) + // stack: x, y, s, retdest %pop3 - %ec_invalid_input + %bn_invalid_input -// Same algorithm as in `exp.asm` -ec_mul_valid_point: - // stack: x, y, s, retdest - DUP3 - // stack: s, x, y, s, retdest - %jumpi(step_case) - // stack: x, y, s, retdest - %jump(ret_zero_ec_mul) - -step_case: - // stack: x, y, s, retdest - PUSH recursion_return - // stack: recursion_return, x, y, s, retdest - PUSH 2 - // stack: 2, recursion_return, x, y, s, retdest - DUP5 - // stack: s , 2, recursion_return, x, y, s, retdest - DIV - // stack: s / 2, recursion_return, x, y, s, retdest - PUSH step_case_contd - // stack: step_case_contd, s / 2, recursion_return, x, y, s, retdest - DUP5 - // stack: y, step_case_contd, s / 2, recursion_return, x, y, s, retdest - DUP5 - // stack: x, y, step_case_contd, s / 2, recursion_return, x, y, s, retdest - %jump(ec_double) - -// Assumption: 2(x,y) = (x',y') -step_case_contd: - // stack: x', y', s / 2, recursion_return, x, y, s, retdest - %jump(ec_mul_valid_point) - -recursion_return: - // stack: x', y', x, y, s, retdest - SWAP4 - // stack: s, y', x, y, x', retdest - PUSH 1 - // stack: 1, s, y', x, y, x', retdest - AND - // stack: s & 1, y', x, y, x', retdest - SWAP1 - // stack: y', s & 1, x, y, x', retdest - SWAP2 - // stack: x, s & 1, y', y, x', retdest - SWAP3 - // stack: y, s & 1, y', x, x', retdest - SWAP4 - // stack: x', s & 1, y', x, y, retdest - SWAP1 - // stack: s & 1, x', y', x, y, retdest - %jumpi(odd_scalar) - // stack: x', y', x, y, retdest - SWAP3 - // stack: y, y', x, x', retdest - POP - // stack: y', x, x', retdest - SWAP1 - // stack: x, y', x', retdest - POP - // stack: y', x', retdest - SWAP2 - // stack: retdest, x', y' +bn_mul_valid_point: + %stack (x, y, s, retdest) -> (s, bn_mul_after_glv, x, y, bn_msm, bn_mul_end, retdest) + %jump(bn_glv_decompose) +bn_mul_after_glv: + // stack: bneg, a, b, x, y, bn_msm, bn_mul_end, retdest + // Store bneg at this (otherwise unused) location. Will be used later in the MSM. + %mstore_kernel(@SEGMENT_KERNEL_BN_TABLE_Q, @BN_BNEG_LOC) + // stack: a, b, x, y, bn_msm, bn_mul_end, retdest + PUSH bn_mul_after_a SWAP1 PUSH @SEGMENT_KERNEL_BN_WNAF_A PUSH @BN_SCALAR %jump(wnaf) +bn_mul_after_a: + // stack: b, x, y, bn_msm, bn_mul_end, retdest + PUSH bn_mul_after_b SWAP1 PUSH @SEGMENT_KERNEL_BN_WNAF_B PUSH @BN_SCALAR %jump(wnaf) +bn_mul_after_b: + // stack: x, y, bn_msm, bn_mul_end, retdest + %jump(bn_precompute_table) +bn_mul_end: + %stack (Ax, Ay, retdest) -> (retdest, Ax, Ay) JUMP - -odd_scalar: - // stack: x', y', x, y, retdest - %jump(ec_add_valid_points) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/glv.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm similarity index 100% rename from evm/src/cpu/kernel/asm/curve/bn254/glv.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm diff --git a/evm/src/cpu/kernel/asm/curve/bn254/msm.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/msm.asm similarity index 100% rename from evm/src/cpu/kernel/asm/curve/bn254/msm.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/msm.asm diff --git a/evm/src/cpu/kernel/asm/curve/bn254/precomputation.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/precomputation.asm similarity index 100% rename from evm/src/cpu/kernel/asm/curve/bn254/precomputation.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/precomputation.asm diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm index c17117ab..414e00ad 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm @@ -129,7 +129,7 @@ mul_tangent_2: DUP6 DUP6 // stack: O, after_double, retdest, 0xnm, times, O, P, Q, out {100: line} - %jump(ec_double) + %jump(bn_double) after_double: // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {100: line} SWAP5 @@ -175,7 +175,7 @@ mul_cord_1: DUP7 DUP7 // stack: O , P, after_add, 0xnm, times, O , P, Q, out - %jump(ec_add_valid_points) + %jump(bn_add_valid_points) after_add: // stack: O + P, 0xnm, times, O , P, Q, out SWAP4 diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_mul.asm deleted file mode 100644 index ecbb3de0..00000000 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_mul.asm +++ /dev/null @@ -1,41 +0,0 @@ -// BN254 elliptic curve scalar multiplication. -// Uses GLV, wNAF with w=5, and a MSM algorithm. -global bn_mul: - // stack: x, y, s, retdest - DUP2 - // stack: y, x, y, s, retdest - DUP2 - // stack: x, y, x, y, s, retdest - %ec_isidentity - // stack: (x,y)==(0,0), x, y, s, retdest - %jumpi(ret_zero_ec_mul) - // stack: x, y, s, retdest - DUP2 - // stack: y, x, y, s, retdest - DUP2 - // stack: x, y, x, y, s, retdest - %bn_check - // stack: isValid(x, y), x, y, s, retdest - %jumpi(bn_mul_valid_point) - // stack: x, y, s, retdest - %pop3 - %bn_invalid_input - -bn_mul_valid_point: - %stack (x, y, s, retdest) -> (s, bn_mul_after_glv, x, y, bn_msm, bn_mul_end, retdest) - %jump(bn_glv_decompose) -bn_mul_after_glv: - // stack: bneg, a, b, x, y, bn_msm, bn_mul_end, retdest - // Store bneg at this (otherwise unused) location. Will be used later in the MSM. - %mstore_kernel(@SEGMENT_KERNEL_BN_TABLE_Q, @BN_BNEG_LOC) - // stack: a, b, x, y, bn_msm, bn_mul_end, retdest - PUSH bn_mul_after_a SWAP1 PUSH @SEGMENT_KERNEL_BN_WNAF_A PUSH @BN_SCALAR %jump(wnaf) -bn_mul_after_a: - // stack: b, x, y, bn_msm, bn_mul_end, retdest - PUSH bn_mul_after_b SWAP1 PUSH @SEGMENT_KERNEL_BN_WNAF_B PUSH @BN_SCALAR %jump(wnaf) -bn_mul_after_b: - // stack: x, y, bn_msm, bn_mul_end, retdest - %jump(bn_precompute_table) -bn_mul_end: - %stack (Ax, Ay, retdest) -> (retdest, Ax, Ay) - JUMP diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm index 3e26d355..9071f396 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm @@ -1,7 +1,5 @@ -/// Division modulo the BN254 prime - -// Returns y * (x^-1) where the inverse is taken modulo N -%macro divfp254 +// Returns reverse order divison y/x, modulo N +%macro divr_fp254 // stack: x , y %inv_fp254 // stack: x^-1, y