Skip to content

Commit

Permalink
Merge branch 'main' into ecPairing
Browse files Browse the repository at this point in the history
  • Loading branch information
IAvecilla committed Sep 19, 2023
2 parents 8a3591b + 95e75d2 commit f51512f
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 195 deletions.
72 changes: 36 additions & 36 deletions precompiles/EcAdd.yul
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@ object "EcAdd" {
m_three := 19052624634359457937016868847204597229365286637454337178037183604060995791063
}

/// @notice Constant function for the alt_bn128 group order.
/// @notice Constant function for the alt_bn128 field order.
/// @dev See https://eips.ethereum.org/EIPS/eip-196 for further details.
/// @return ret The alt_bn128 group order.
function ALT_BN128_GROUP_ORDER() -> ret {
/// @return ret The alt_bn128 field order.
function ALT_BN128_FIELD_ORDER() -> ret {
ret := 21888242871839275222246405745257275088696311157297823662689037894645226208583
}

/// @notice Constant function for the pre-computation of R^2 % N for the Montgomery REDC algorithm.
/// @dev R^2 is the Montgomery residue of the value 2^512.
/// @dev See https://en.wikipedia.org/wiki/Montgomery_modular_multiplication#The_REDC_algorithm for further detals.
/// @dev This value was precomputed using Python.
/// @return ret The value R^2 modulus the curve group order.
function R2_MOD_ALT_BN128_GROUP_ORDER() -> ret {
/// @return ret The value R^2 modulus the curve field order.
function R2_MOD_ALT_BN128_FIELD_ORDER() -> ret {
ret := 3096616502983703923843567936837374451735540968419076528771170197431451843209
}

/// @notice Constant function for the pre-computation of N' for the Montgomery REDC algorithm.
/// @dev N' is a value such that NN' = -1 mod R, with N being the curve group order.
/// @dev N' is a value such that NN' = -1 mod R, with N being the curve field order.
/// @dev See https://en.wikipedia.org/wiki/Montgomery_modular_multiplication#The_REDC_algorithm for further detals.
/// @dev This value was precomputed using Python.
/// @return ret The value N'.
Expand Down Expand Up @@ -105,7 +105,7 @@ object "EcAdd" {
let ySquared := montgomeryMul(y, y)
let xSquared := montgomeryMul(x, x)
let xQubed := montgomeryMul(xSquared, x)
let xQubedPlusThree := addmod(xQubed, MONTGOMERY_THREE(), ALT_BN128_GROUP_ORDER())
let xQubedPlusThree := addmod(xQubed, MONTGOMERY_THREE(), ALT_BN128_FIELD_ORDER())

ret := eq(ySquared, xQubedPlusThree)
}
Expand All @@ -120,26 +120,26 @@ object "EcAdd" {
ret := and(iszero(x), iszero(y))
}

/// @notice Checks if a coordinate is on the curve group order.
/// @dev A coordinate is on the curve group order if it is on the range [0, curveGroupOrder).
/// @notice Checks if a coordinate is on the curve field order.
/// @dev A coordinate is on the curve field order if it is on the range [0, curveFieldOrder).
/// @dev This check is required in the precompile specification. See https://eips.ethereum.org/EIPS/eip-196 for further details.
/// @param coordinate The coordinate to check.
/// @return ret True if the coordinate is in the range, false otherwise.
function isOnGroupOrder(coordinate) -> ret {
ret := lt(coordinate, ALT_BN128_GROUP_ORDER())
function isOnFieldOrder(coordinate) -> ret {
ret := lt(coordinate, ALT_BN128_FIELD_ORDER())
}

function binaryExtendedEuclideanAlgorithm(base) -> inv {
// Precomputation of 1 << 255
let mask := 57896044618658097711785492504343953926634992332820282019728792003956564819968
let modulus := ALT_BN128_GROUP_ORDER()
let modulus := ALT_BN128_FIELD_ORDER()
// modulus >> 255 == 0 -> modulus & 1 << 255 == 0
let modulusHasSpareBits := iszero(and(modulus, mask))

let u := base
let v := modulus
// Avoids unnecessary reduction step.
let b := R2_MOD_ALT_BN128_GROUP_ORDER()
let b := R2_MOD_ALT_BN128_FIELD_ORDER()
let c := ZERO()

for {} and(iszero(eq(u, ONE())), iszero(eq(v, ONE()))) {} {
Expand Down Expand Up @@ -212,14 +212,14 @@ object "EcAdd" {
/// @return S The result of the Montgomery reduction.
function REDC(lowestHalfOfT, higherHalfOfT) -> S {
let q := mul(lowestHalfOfT, N_PRIME())
let aHigh := add(higherHalfOfT, getHighestHalfOfMultiplication(q, ALT_BN128_GROUP_ORDER()))
let aLow, overflowed := overflowingAdd(lowestHalfOfT, mul(q, ALT_BN128_GROUP_ORDER()))
let aHigh := add(higherHalfOfT, getHighestHalfOfMultiplication(q, ALT_BN128_FIELD_ORDER()))
let aLow, overflowed := overflowingAdd(lowestHalfOfT, mul(q, ALT_BN128_FIELD_ORDER()))
if overflowed {
aHigh := add(aHigh, ONE())
}
S := aHigh
if iszero(lt(aHigh, ALT_BN128_GROUP_ORDER())) {
S := sub(aHigh, ALT_BN128_GROUP_ORDER())
if iszero(lt(aHigh, ALT_BN128_FIELD_ORDER())) {
S := sub(aHigh, ALT_BN128_FIELD_ORDER())
}
}

Expand All @@ -228,9 +228,9 @@ object "EcAdd" {
/// @param a The field element to encode.
/// @return ret The field element in Montgomery form.
function intoMontgomeryForm(a) -> ret {
let temp := mod(a, ALT_BN128_GROUP_ORDER())
let higherHalf := getHighestHalfOfMultiplication(temp, R2_MOD_ALT_BN128_GROUP_ORDER())
let lowestHalf := mul(temp, R2_MOD_ALT_BN128_GROUP_ORDER())
let temp := mod(a, ALT_BN128_FIELD_ORDER())
let higherHalf := getHighestHalfOfMultiplication(temp, R2_MOD_ALT_BN128_FIELD_ORDER())
let lowestHalf := mul(temp, R2_MOD_ALT_BN128_FIELD_ORDER())
ret := REDC(lowestHalf, higherHalf)
}

Expand Down Expand Up @@ -295,8 +295,8 @@ object "EcAdd" {
if and(p1IsInfinity, iszero(p2IsInfinity)) {
// Infinity + P = P

// Ensure that the coordinates are between 0 and the group order.
if or(iszero(isOnGroupOrder(x2)), iszero(isOnGroupOrder(y2))) {
// Ensure that the coordinates are between 0 and the field order.
if or(iszero(isOnFieldOrder(x2)), iszero(isOnFieldOrder(y2))) {
burnGas()
revert(0, 0)
}
Expand All @@ -320,8 +320,8 @@ object "EcAdd" {
if and(iszero(p1IsInfinity), p2IsInfinity) {
// P + Infinity = P

// Ensure that the coordinates are between 0 and the group order.
if or(iszero(isOnGroupOrder(x1)), iszero(isOnGroupOrder(y1))) {
// Ensure that the coordinates are between 0 and the field order.
if or(iszero(isOnFieldOrder(x1)), iszero(isOnFieldOrder(y1))) {
burnGas()
revert(0, 0)
}
Expand All @@ -343,19 +343,19 @@ object "EcAdd" {
return(0, 64)
}

// Ensure that the coordinates are between 0 and the group order.
if or(iszero(isOnGroupOrder(x1)), iszero(isOnGroupOrder(y1))) {
// Ensure that the coordinates are between 0 and the field order.
if or(iszero(isOnFieldOrder(x1)), iszero(isOnFieldOrder(y1))) {
burnGas()
}

// Ensure that the coordinates are between 0 and the group order.
if or(iszero(isOnGroupOrder(x2)), iszero(isOnGroupOrder(y2))) {
// Ensure that the coordinates are between 0 and the field order.
if or(iszero(isOnFieldOrder(x2)), iszero(isOnFieldOrder(y2))) {
burnGas()
}

// There's no need for transforming into Montgomery form
// for this case.
if and(eq(x1, x2), eq(submod(0, y1, ALT_BN128_GROUP_ORDER()), y2)) {
if and(eq(x1, x2), eq(submod(0, y1, ALT_BN128_FIELD_ORDER()), y2)) {
// P + (-P) = Infinity

let m_x1 := intoMontgomeryForm(x1)
Expand All @@ -377,7 +377,7 @@ object "EcAdd" {
return(0, 64)
}

if and(eq(x1, x2), and(iszero(eq(y1, y2)), iszero(eq(y1, submod(0, y2, ALT_BN128_GROUP_ORDER()))))) {
if and(eq(x1, x2), and(iszero(eq(y1, y2)), iszero(eq(y1, submod(0, y2, ALT_BN128_FIELD_ORDER()))))) {
burnGas()
}

Expand All @@ -395,11 +395,11 @@ object "EcAdd" {

// (3 * x1^2 + a) / (2 * y1)
let x1_squared := montgomeryMul(x, x)
let slope := montgomeryDiv(addmod(x1_squared, addmod(x1_squared, x1_squared, ALT_BN128_GROUP_ORDER()), ALT_BN128_GROUP_ORDER()), addmod(y, y, ALT_BN128_GROUP_ORDER()))
let slope := montgomeryDiv(addmod(x1_squared, addmod(x1_squared, x1_squared, ALT_BN128_FIELD_ORDER()), ALT_BN128_FIELD_ORDER()), addmod(y, y, ALT_BN128_FIELD_ORDER()))
// x3 = slope^2 - 2 * x1
let x3 := submod(montgomeryMul(slope, slope), addmod(x, x, ALT_BN128_GROUP_ORDER()), ALT_BN128_GROUP_ORDER())
let x3 := submod(montgomeryMul(slope, slope), addmod(x, x, ALT_BN128_FIELD_ORDER()), ALT_BN128_FIELD_ORDER())
// y3 = slope * (x1 - x3) - y1
let y3 := submod(montgomeryMul(slope, submod(x, x3, ALT_BN128_GROUP_ORDER())), y, ALT_BN128_GROUP_ORDER())
let y3 := submod(montgomeryMul(slope, submod(x, x3, ALT_BN128_FIELD_ORDER())), y, ALT_BN128_FIELD_ORDER())

x3 := outOfMontgomeryForm(x3)
y3 := outOfMontgomeryForm(y3)
Expand All @@ -422,11 +422,11 @@ object "EcAdd" {
}

// (y2 - y1) / (x2 - x1)
let slope := montgomeryDiv(submod(y2, y1, ALT_BN128_GROUP_ORDER()), submod(x2, x1, ALT_BN128_GROUP_ORDER()))
let slope := montgomeryDiv(submod(y2, y1, ALT_BN128_FIELD_ORDER()), submod(x2, x1, ALT_BN128_FIELD_ORDER()))
// x3 = slope^2 - x1 - x2
let x3 := submod(montgomeryMul(slope, slope), addmod(x1, x2, ALT_BN128_GROUP_ORDER()), ALT_BN128_GROUP_ORDER())
let x3 := submod(montgomeryMul(slope, slope), addmod(x1, x2, ALT_BN128_FIELD_ORDER()), ALT_BN128_FIELD_ORDER())
// y3 = slope * (x1 - x3) - y1
let y3 := submod(montgomeryMul(slope, submod(x1, x3, ALT_BN128_GROUP_ORDER())), y1, ALT_BN128_GROUP_ORDER())
let y3 := submod(montgomeryMul(slope, submod(x1, x3, ALT_BN128_FIELD_ORDER())), y1, ALT_BN128_FIELD_ORDER())

x3 := outOfMontgomeryForm(x3)
y3 := outOfMontgomeryForm(y3)
Expand Down
Loading

0 comments on commit f51512f

Please sign in to comment.