Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add G2 subgroup check for ECPAIRING #268

Merged
merged 10 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion evm_arithmetization/src/cpu/kernel/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ pub(crate) fn combined_kernel() -> Kernel {
include_str!("asm/curve/bn254/curve_arithmetic/msm.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/pairing.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/precomputation.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve_add.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve_checks.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve_endomorphism.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve_mul.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"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ global bn_add:
%bn_check
// stack: isValid(x0, y0), x0, y0, x1, y1, retdest
DUP5
// stack: x1, isValid(x0, y0), x0, y0, x1, y1, retdest
// stack: y1, 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
MUL // Cheaper than AND
// stack: isValid(x1, y1) & isValid(x0, y0), x0, y0, x1, y1, retdest
%jumpi(bn_add_valid_points)
// stack: x0, y0, x1, y1, retdest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,16 @@ bn254_input_check:
// stack: inp_j', inp_j, j, k, inp
%load_fp254_4
// stack: Q_j, inp_j, j, k, inp
%dup_bn_g2
// stack: Q_j, Q_j, inp_j, j, k, inp
%bn_check_twisted
// stack: valid?, inp_j, j, k, inp
ISZERO
// stack: valid_1?, Q_j, inp_j, j, k, inp
%stack (b, Q: 4) -> (Q, b)
%bn_check_twisted_subgroup
ISZERO
// stack: valid_2?, valid_1?, inp_j, j, k, inp
ADD // Cheaper than OR
%jumpi(bn_pairing_invalid_input)
// stack: inp_j, j, k, inp
POP
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// Elliptic curve addition on the twist of BN254 curve.
// Assumption: (X0,Y0) is a valid point.
// Uses the standard affine addition formula.
global bn_twisted_add:
// stack: X0: 2, Y0: 2, X1: 2, Y1: 2, retdest

// Check if the first point is the identity.
%dup_fp254_2_2
// stack: Y0, X0, Y0, X1, Y1, retdest
%dup_fp254_2_2
// stack: X0, Y0, X0, Y0, X1, Y1, retdest
%bn_check_twisted_ident
// stack: (X0,Y0)==(0,0), X0, Y0, X1, Y1, retdest
%jumpi(bn_twisted_add_fst_zero)
// stack: X0, Y0, X1, Y1, retdest

// Check if the second point is the identity.
%dup_fp254_2_6
// stack: Y1, X0, Y0, X1, Y1, retdest
%dup_fp254_2_6
// stack: X1, Y1, X0, Y0, X1, Y1, retdest
%bn_check_twisted_ident
// stack: (X1,Y1)==(0,0), X0, Y0, X1, Y1, retdest
%jumpi(bn_twisted_add_snd_zero)
// stack: X0, Y0, X1, Y1, retdest

// Check if both points have the same X-coordinate.
%dup_fp254_2_4
// stack: X1, X0, Y0, X1, Y1, retdest
%dup_fp254_2_2
// stack: X0, X1, X0, Y0, X1, Y1, retdest
%eq_fp254_2
// stack: X0 == X1, X0, Y0, X1, Y1, retdest
%jumpi(bn_twisted_add_equal_first_coord)
// stack: X0, Y0, X1, Y1, retdest

// Otherwise, we can use the standard formula.
// Compute lambda = (Y0 - Y1)/(X0 - X1)
%dup_fp254_2_6
// stack: Y1, X0, Y0, X1, Y1, retdest
%dup_fp254_2_4
// stack: Y0, Y1, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: Y0 - Y1, X0, Y0, X1, Y1, retdest
%dup_fp254_2_6
// stack: X1, Y0 - Y1, X0, Y0, X1, Y1, retdest
%dup_fp254_2_4
// stack: X0, X1, Y0 - Y1, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: X0 - X1, Y0 - Y1, X0, Y0, X1, Y1, retdest
%divr_fp254_2
// stack: lambda, X0, Y0, X1, Y1, retdest
%jump(bn_twisted_add_valid_points_with_lambda)

// BN254 twisted elliptic curve addition.
// Assumption: (X0,Y0) == (0,0)
bn_twisted_add_fst_zero:
// stack: X0: 2, Y0: 2, X1: 2, Y1: 2, retdest
// Just return (X1, Y1)
%stack (X0: 2, Y0: 2, X1: 2, Y1: 2, retdest) -> (retdest, X1, Y1)
JUMP

// BN254 twisted elliptic curve addition.
// Assumption: (X1,Y1) == (0,0)
bn_twisted_add_snd_zero:
// stack: X0: 2, Y0: 2, X1: 2, Y1: 2, retdest

// Just return (X0,Y0)
%stack (X0: 2, Y0: 2, X1: 2, Y1: 2, retdest) -> (retdest, X0, Y0)
JUMP

// BN254 twisted elliptic curve addition.
// Assumption: lambda = (Y0 - Y1)/(X0 - X1)
bn_twisted_add_valid_points_with_lambda:
// stack: lambda: 2, X0: 2, Y0: 2, X1: 2, Y1: 2, retdest

// Compute X2 = lambda^2 - X1 - X0
%dup_fp254_2_2
// stack: X0, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_8
// stack: X1, X0, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_4
// stack: lambda, X1, X0, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_0
// stack: lambda, lambda, X1, X0, lambda, X0, Y0, X1, Y1, retdest
%mul_fp254_2
// stack: lambda^2, X1, X0, lambda, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: lambda^2 - X1, X0, lambda, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: X2, lambda, X0, Y0, X1, Y1, retdest

// Compute Y2 = lambda*(X1 - X2) - Y1
%dup_fp254_2_0
// stack: X2, X2, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_10
// stack: X1, X2, X2, lambda, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: X1 - X2, X2, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_4
// stack: lambda, X1 - X2, X2, lambda, X0, Y0, X1, Y1, retdest
%mul_fp254_2
// stack: lambda * (X1 - X2), X2, lambda, X0, Y0, X1, Y1, retdest
%dup_fp254_2_12
// stack: Y1, lambda * (X1 - X2), X2, lambda, X0, Y0, X1, Y1, retdest
%stack (Y1: 2, T: 2) -> (T, Y1)
// stack: lambda * (X1 - X2), Y1, X2, lambda, X0, Y0, X1, Y1, retdest
%sub_fp254_2
// stack: Y2, X2, lambda, X0, Y0, X1, Y1, retdest

// Return X2, Y2
%stack (Y2: 2, X2: 2, lambda: 2, X0: 2, Y0: 2, X1: 2, Y1: 2, retdest) -> (retdest, X2, Y2)
JUMP

// BN254 twisted elliptic curve addition.
// Assumption: (X0,Y0) and (X1,Y1) are valid points and X0 == X1
bn_twisted_add_equal_first_coord:
// stack: X0, Y0, X1, Y1, retdest with X0 == X1

// Check if the points are equal
%dup_fp254_2_2
// stack: Y0, X0, Y0, X1, Y1, retdest
%dup_fp254_2_8
// stack: Y1, Y0, X0, Y0, X1, Y1, retdest
%eq_fp254_2
// stack: Y1 == Y0, X0, Y0, X1, Y1, retdest
%jumpi(bn_twisted_add_equal_points)
// stack: X0, Y0, X1, Y1, retdest

// Otherwise, one is the negation of the other so we can return the identity.
%stack (garbage: 8, retdest) -> (retdest, 0, 0, 0, 0)
// stack: retdest, X=0, Y=0
JUMP


// BN254 twisted elliptic curve addition.
// Assumption: X0 == X1 and Y0 == Y1
// Standard doubling formula.
bn_twisted_add_equal_points:
// stack: X0, Y0, X1, Y1, retdest

// Compute lambda = 3/2 * X0^2 / Y0
%dup_fp254_2_0
// stack: X0, X0, Y0, X1, Y1, retdest
%dup_fp254_2_0
// stack: X0, X0, X0, Y0, X1, Y1, retdest
%mul_fp254_2
// stack: X0^2, X0, Y0, X1, Y1, retdest
PUSH 0X183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea5 // 3/2 in the base field
// stack: 3/2, X0^2, X0, Y0, X1, Y1, retdest
%scale_fp254_2
// stack: 3/2 * X0^2, X0, Y0, X1, Y1, retdest
%dup_fp254_2_4
// stack: Y0, 3/2 * X0^2, X0, Y0, X1, Y1, retdest
%divr_fp254_2
// stack: lambda, X0, Y0, X1, Y1, retdest
%jump(bn_twisted_add_valid_points_with_lambda)

// BN254 twisted elliptic curve doubling.
// Assumption: (X0,Y0) is a valid point.
// Standard doubling formula.
global bn_twisted_double:
// stack: X, Y, retdest
%dup_bn_g2
// stack: X, Y, X, Y, retdest
%bn_check_twisted_ident
// stack: (X,Y)==(0,0), X, Y, retdest
%jumpi(ec_twisted_double_retself)
%dup_bn_g2
// stack: X, Y, X, Y, retdest
%jump(bn_twisted_add_equal_points)

// Convenience macro to call bn_twisted_add and return where we left off.
%macro bn_twisted_add
%stack (X0: 2, Y0: 2, X1: 2, Y1: 2) -> (X0, Y0, X1, Y1, %%after)
%jump(bn_twisted_add)
%%after:
%endmacro

%macro bn_twisted_sub
// stack: X0: 2, Y0: 2, X1: 2, Y1: 2
%swap_fp254_2_4
// stack: Y1, Y0, X1, X0
PUSH 0 PUSH 0
%sub_fp254_2
// stack: -Y1, Y0, X1, X0
%stack (Y1: 2, Y0: 2, X1: 2, X0: 2) -> (X0, Y0, X1, Y1, %%after)
%jump(bn_twisted_add)
%%after:
%endmacro

// Convenience macro to call bn_twisted_double and return where we left off.
%macro bn_twisted_double
%stack (X: 2, Y: 2) -> (X, Y, %%after)
%jump(bn_twisted_double)
%%after:
%endmacro
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,52 @@
MUL // Cheaper than AND
MUL // Cheaper than AND
%endmacro

/// The `ECPAIRING` precompile requires checking that G2
/// inputs are on the correct prime-order subgroup.
/// This macro performs this check, based on the algorithm
/// detailed in <https://eprint.iacr.org/2022/348.pdf>.
%macro bn_check_twisted_subgroup
// stack: Q = (X, Y)
%dup_bn_g2
// stack: Q, Q
%bn_twisted_mul_by_z
// stack: zQ, Q
%dup_bn_g2
// stack: zQ, zQ, Q
%swap_bn_g2_2
// stack: Q, zQ, zQ
%bn_twisted_add
// stack: [z+1]Q, zQ
%swap_bn_g2
// stack: zQ, [z+1]Q
%bn_endomorphism
// stack: phi(zQ), [z+1]Q
%dup_bn_g2
// stack: phi(zQ), phi(zQ), [z+1]Q
%bn_endomorphism
// stack: phi^2(zQ), phi(zQ), [z+1]Q
%dup_bn_g2
// stack: phi^2(zQ), phi^2(zQ), phi(zQ), [z+1]Q
%bn_endomorphism
// stack: phi^3(zQ), phi^2(zQ), phi(zQ), [z+1]Q
%bn_twisted_double
// stack: phi^3([2z]Q), phi^2(zQ), phi(zQ), [z+1]Q
%bn_twisted_sub
// stack: phi^3([2z]Q) - phi^2(zQ), phi(zQ), [z+1]Q
%bn_twisted_sub
// stack: phi^3([2z]Q) - phi^2(zQ) - phi(zQ), [z+1]Q
%bn_twisted_sub
// stack: phi^3([2z]Q) - phi^2(zQ) - phi(zQ) - [z+1]Q
%bn_check_twisted_ident
// stack: is_ident
%endmacro

// Return [(u256::MAX, u256::MAX), (u256::MAX, u256::MAX)] which is used to indicate the input was invalid.
%macro bn_twisted_invalid_input
// stack: retdest
PUSH @U256_MAX
// stack: u256::MAX, retdest
%stack (max, retdest) -> (retdest, max, max, max, max)
JUMP
%endmacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Implementation of the BN254 twist endomorphism.

/// Frobenius map over BN254 quadratic extension.
%macro frob_fp254_2
// stack: X = (x, x_)
%conj_fp254_2
// stack: frob(X)
%endmacro

%macro bn_endomorphism
// stack: X: 2, Y: 2
%frob_fp254_2
// stack: X', Y
%swap_fp254_2
// stack: Y, X'
%frob_fp254_2
// stack: Y', X'
PUSH @BN_ENDO_Y_COORD_IM
PUSH @BN_ENDO_Y_COORD_RE
%mul_fp254_2
// stack: φ_y.Y', X'
%swap_fp254_2
// stack: X', φ_y.Y'
PUSH @BN_ENDO_X_COORD_IM
PUSH @BN_ENDO_X_COORD_RE
%mul_fp254_2
// stack: φ_x.X', φ_y.Y'
%endmacro
Loading