- BLS12-381
- Input format
- BigInt templates
- BigInt functions
log_ceil(n)long_add(n, k, a, b)long_add_unequal(n, k1, k2, a, b)long_sub(n, k, a, b)long_scalar_mult(n, k, a, b)long_div2(n, k, m, a, b)signed_long_to_short(n, k, a)prod(n, k, a, b)prod2D(n, k, l, a, b)long_add_mod(n, k, a, b, p)long_sub_mod(n, k, a, b, p)prod_mod(n, k, a, b, p)mod_exp(n, k, a, p, e)mod_inv(n, k, a, p)
- Fp templates
- Fp2 templates
SignedFp2MultiplyNoCarryUnequal(n, ka, kb, m_out)SignedFp2MultiplyNoCarry(n, k, m_out)Fp2Compress(n, k, m, p, m_out)SignedFp2MultiplyNoCarryCompress(n, k, p, m_in, m_out)SignedFp2MultiplyNoCarryCompressThree(n, k, p, m_in, m_out)RangeCheck2D(n, k)SignedFp2CarryModP(n, k, overflow, p)Fp2Multiply(n, k, p)Fp2MultiplyThree(n, k, p)Fp2Negate(n, k, p)Fp2Invert(n, k, p)SignedFp2Divide(n, k, overflowa, overflowb, p)Fp2Conjugate(n, k, p)Fp2FrobeniusMap(n, k, power, p)Fp2Sgn0(n, k, p)Fp2IsZero(n, k, p)Fp2IsEqual(n, k, p)
- Fp12 templates
Fp12FrobeniusMap(n, k, power)SignedFp12ScalarMultiplyNoCarryUnequal(n, ka, kb, m_out)SignedFp12ScalarMultiplyNoCarry(n, k, m_out)SignedFp12Fp2MultiplyNoCarryUnequal(n, ka, kb, m_out)SignedFp12Fp2MultiplyNoCarry(n, k, m_out)SignedFp12MultiplyNoCarryUnequal(n, ka, kb, m_out)SignedFp12MultiplyNoCarry(n, k, m_out)Fp12Compress(n, k, m, p, m_out)SignedFp12MultiplyNoCarryCompress(n, k, p, m_in, m_out)SignedFp12CarryModP(n, k, overflow, p)Fp12Multiply(n, k, p)Fp12Invert(n, k, p)
- Finite field functions
get_fp_sng0(a)find_Fp_inverse(n, k, num, p)get_signed_Fp_carry_witness(n, k, m, a, p)get_signed_Fp2_carry_witness(n, k, m, a, p)get_fp2_sgn0(k, a)find_Fp2_product(n, k, a, b, p)find_Fp2_sum(n, k, a, b, p)find_Fp2_diff(n, k, a, b, p)find_Fp2_exp(n, k, a, p, e)is_equal_Fp2(n, k, a, b)signed_Fp2_mult_w6(k, a, XI0)find_Fp12_sum(n, k, a, b, p)find_Fp12_diff(n, k, a, b, p)find_Fp12_product(n, k, a, b, p)find_Fp2_inverse(n, k, a, p)find_Fp6_inverse(n, k, p, a0, a1, a2)find_Fp12_inverse(n, k, p, a)
- Elliptic curve templates
PointOnLine(n, k, p)PointOnCurve(n, k, a, b, p)PointOnTangent(n, k, a, p)EllipticCurveAddUnequal(n, k, p)EllipticCurveDouble(n, k, a, b, p)EllipticCurveAdd(n, k, p)EllipticCurveScalarMultiply(n, k, b, x, p)EllipticCurveScalarMultiplyUnequal(n, k, b, x, p)SignedLineFunctionUnequalNoCarry(n, k, m_out)SignedLineFunctionEqualNoCarry(n, k, m_out)LineFunctionUnequal(n, k, p)LineFunctionEqual(n, k, p)Fp12MultplyWithLineUnequal(n, k, kg, overflowg, p)MillerLoop(n, k, b, x, p)BLSMillerLoop(n, k, p)
- Elliptic curve over
F_{p^2}templatesPointOnLineFp2(n, k, p)PointOnCurveFp2(n, k, a, b, p)EllipticCurveFunction(n, k, a, b, p)PointOnTangentFp2(n, k, a, p)EllipticCurveAddUnequalFp2(n, k, p)EllipticCurveDoubleFp2(n, k, a, b, p)EllipticCurveAddFp2(n, k, p)EllipticCurveScalarMultiplyFp2(n, k, b, x, p)EllipticCurveScalarMultiplyUnequalFp2(n, k, b, x, p)SignedLineFunctionUnequalNoCarryFp2(n, k, m_out)SignedLineFunctionEqualNoCarryFp2(n, k, m_out)LineFunctionUnequalFp2(n, k, p)LineFunctionEqualFp2(n, k, p)Fp12MultplyWithLineUnequalFp2(n, k, kg, overflowg, p)MillerLoopFp2(n, k, b, x, p)MillerLoopFp2Two(n, k, b, x, p)
- Final exponentiation templates
- BLS12-381 Map to G2 and subgroup checks
- Pairing templates
- BLS Signature templates
We refer to BLS12-381 For The Rest Of Us for details about the curve BLS12-381.
The curve E is
y^2 = x^3 + 4
over F_q for a 381-bit prime q.
The twist E2 of E is the curve
y^2 = x^3 + 4(1+u)
over F_{q^2} (see below).
For general implementations not particular to BLS12-381, we denote the prime by p below.
To format inputs correctly for our circuits, in Python one can use the functions in python/field_helper.py which are designed to work with py_ecc. In Typescript one can see test/test.ts for an example of how to format inputs compatibly with @noble/bls12-381.
Almost every template we use contains two parameters n and k (in practice we use n = 55, k = 7), where n denotes the register bit size and k denotes the number of registers: for a large integer A we can represent it as an array a of length k such that
A = 2^0 * a[0] + 2^n * a[1] + ... + 2^{n(k-1)} * a[k-1]
where each register 0 <= a[i] < 2^n for all i. In other words, this is base 2^n little-endian notation. We call this a proper BigInt representation.
For the purposes of optimizing constraints, in many intermediate circuits we store a big integer in the form
A = 2^0 * a[0] + 2^n * a[1] + ... + 2^{n(k-1)} * a[k-1]
where each register a[i] is signed and allowed to have absolute value possibly larger than 2^n. Here signed means: for a positive number 0 <= b < 2^252, we can store -b as BabyJubJubPrime - b > 2^252, where BabyJubJubPrime is the inherent 254-bit field modulus in circom.
Since we store numbers in this overflow representation, we need to make sure that as we perform other operations (such as multiplying two numbers), the absolute value of each array element stays < 2^252. This will involve keeping track of various bounds that we make note of both in this documentation and in the code.
An element in F_p uniquely corresponds to an integer 0 <= A < p.
While our witness generation always produces F_p elements 0 <= A < p, to save constraints we usually only constrain A >= 0 to be a proper BigInt and further constrain A < p only when necessary. In other words, unless otherwise specified, we constrain an F_p element representing A to be any proper BigInt (necessarily < 2^{n*k}) congruent to A modulo p.
We construct F_{p^2} = F_p[u]/(u^2+1) (this requires p = 3 (mod 4)). An element in F_{p^2} has the form
A_0 + A_1 u
with A_0, A_1 in F_p. We represent this element as a 2 x k array a with a[0], a[1] in F_p (with the same caveats as above).
We construct F_{p^12} = F_{p^2}[w]/(w^6 - (1+u)) (this requires 1+u to not be a square or cube in F_{p^2}). An element in F_{p^12} has the form
\sum_{i=0}^5 A_i w^i
for A_i in F_{p^2}. We represent it as a 6 x 2 x k array a where a[i] represents A_i.
A point in E(F_p) is a pair (x, y) with x,y in F_p so we represent it as a 2 x k array P where P[0] represents x and P[1] represents y.
A point in E_2(F_{p^2}) is a pair (x, y) with x,y in F_{p^2} so we represent it as a 2 x 2 x k array Q where Q[0] represents x and Q[1] represents y.
A point in E(F_{p^12}) is a pair (X, Y) with X,Y in F_{p^12} so we represent it as a 2 x 6 x 2 x k array Q where Q[0] represents x and Q[1] represents y.
bigint.circom is a fork of circom-ecdsa, containing templates for operating on numbers represented in array form (usually because the number may exceed the size of the circom prime BabyJubJubPrime). See Input format for a review of different ways to represent numbers.
Here are the main circuits we use from bigint.circom:
Multiplication of two polynomials in one variable X.
Inputs:
a = a[0] + a[1] * X + ... + a[k-1] * X^{k-1}a degreek - 1polynomialb = b[0] + b[1] * X + ... + b[k-1] * X^{k-1}a degreek - 1polynomial
Output:
out = out[0] + out[1] * X + ... + out[2 * k - 2] * X^{2*k - 2}out = a * bas polynomials inX
Notes:
- Optimization due to xJsnark:
- witness is calculated by normal polynomial multiplication
outis contrained by evaluatingout(X) === a(X) * b(X)atX = 0, ..., 2*k - 2
- If all
a[i], b[i]have absolute values< B, thenout[i]has absolute value< k * B^2
For code readability/verification, m_out is passed as a parameter with the expected max number of bits in the output registers out[i].
This is the same as BigMultShortLong except a has degree ka - 1 and b has degree kb - 1.
- If all
a[i], b[i]have absolute values< B, thenout[i]has absolute value< min(ka, kb) * B^2
Inputs:
a,bin BigInt format
Output:
out = (a < b) ? 1 : 0
Inputs:
- BigInts
a,b - Assume
a >= b
Output:
- BigInt
out = a - b underflow= how much is borrowed at the highest register of subtraction, only nonzero ifa < b
Input:
in = in[0] + in[1] * X + ... + in[k-1] * X^{k-1}as signed overflow representation- Assume each
in[i]is in range(-2^{m-1}, 2^{m-1}). - Assume
m < 252.
Implements:
- Constrain that
inevaluated atX = 2^nas a big integer equals zero. - Costs roughly
k * (m - n)constraints.
This template compresses the array length of a signed overflow BigInt at the cost of increasing the overflow size.
Input: Let X = 2^n.
inis lengthk + marray in signed overflow representationin = in[0] + in[1] * X + ... + in[k+m-1] * X^{k+m-1}- Assume each
in[i]is a signed integer such thatabs(in[i] * 2^n) < 2^252 pis prime in proper BigInt format passed as parameter.
Output:
out = out[0] + out[1] * X + ... + out[k-1] * X^{k-1}is BigInt congruent toin (mod p)
Implementation:
- For
i >= k, we precomputeX^i = r[i] mod p, wherer[i][]is a proper BigInt< p. in[i] * X^iis replaced bysum_j in[i] * r[i][j] * X^j- If each
in[i]has absolute value<B, thenout[i]has absolute value< (m+1) * 2^n * B.
m_out is the expected max number of bits in the output registers.
Polynomial multiplication in 2 variables.
Input:
a = sum_{i=0}^{l-1} sum_{j=0}^{k-1} a[i][j] * w^i * X^jb = sum_{i=0}^{l-1} sum_{j=0}^{k-1} b[i][j] * w^i * X^j
Output:
out = sum_{i=0}^{2*l-2} sum_{j=0}^{2*k-1} out[i][j] * w^i * X^jout = a * bas product of polynomials in two variablesw, X
Implementation:
- Uses same xJsnark optimization as
BigMultShortLong - If
a[i][j], b[i][j]have absolute value< B, thenout[i][j]has absolute value< l * k * B^2.
Use case: one variable will end up being 2^n; the other will be the field extension generator.
bigint_func.circom contains helper functions for witness generation on proper BigInts represented in array form. The parameters n,k always mean the register bit size and number of registers. Unless otherwise specified, BigInts are always represented in proper format.
Parameters:
n: an integer assumed< 2^253.
Outputs:
- Returns
$\lceil \log_2 n\rceil$ .
Parameters:
a: BigInt withkregistersb: BigInt withkregisters
Outputs:
- Returns BigInt
out = a + bwithk + 1registers.
Assumptions:
- Assumes
k+1 <= 50(becausevararray sizes are static).
Parameters:
a: BigInt withk1registersb: BigInt withk2registers
Outputs:
- Returns BigInt
out = a + bwithk1 + 1registers.
Assumptions:
- Assumes
k1 >= k2andk1 + 1 <= 50.
Parameters:
a: BigInt withkregistersb: BigInt withkregisters
Outputs:
- Returns BigInt
out = a - b.
Assumptions:
- Assumes
a >= bandk <= 50.
Parameters:
a:n-bit integer.b: BigInt withkregisters
Outputs:
- Returns a BigInt
out = a * bwithk+1registers.
Assumptions:
- Assumes
k+1 <= 50.
Parameters:
a: BigInt withk + mregistersb: BigInt withkregisters
Outputs:
- Returns BigInt
out[0]withm + 1registers andout[1]withkregisters such thata = out[0] * b + out[1].
Assumptions:
- Assumes
k + m <= 50. - Assumes
b[k-1]is nonzero.
Parameters:
a: BigInt in signed overflow representation withkregisters.
Outputs:
- Returns a length
50arrayoutrepresentingain proper BigInt form. out[50] = 0ifais positive,1ifais negative.
Assumptions:
- Assumes
a[i] < 2^{252}for alliand that the proper representation ofauses at most50registers. (Anassertwill fail otherwise.)
Parameters:
a: BigInt withkregistersb: BigInt withkregisters
Outputs:
- Returns BigInt
out = a * bwith2k - 1registers.
Note that the difference between prod and BigMultShortLong is that the registers of out here are in [0, 2^n). We are no longer doing polynomial multiplication and must "carry" using base 2^n.
Assumptions:
- Assumes
k <= 25.
Parameters:
a: lengthl x karray representing a degreel - 1polynomiala = a[0] + a[1] * w + ... + a[l-1] * w^{l-1}witha[i]BigInts withkregisters.b: lengthl x karray representing a degreel - 1polynomialb = b[0] + b[1] * w + ... + b[l-1] * w^{l-1}withb[i]BigInts withkregisters.
Outputs:
- Returns length
2l - 1 x 2karray representingout = a * bas product of polynomials inw. out = out[0] + out[1] * w + ... + out[2l-2] * w^{2l-2}
Note that the difference between prod2D and BigMultShortLong2D is that the registers of out here are in [0, 2^n). Despite the name, prod2D is multiplication of polynomials in one variable, whereas BigMultShortLong2D is multiplication of polynomials in two variables.
Assumptions:
k <= 25l <= 10
These are the same as long_add, long_sub, prod except we return out % p as BigInts. Note that long_sub_mod assumes that a,b < p.
Parameters:
a: BigInt withkregistersp: BigInt withkregisters (notepdoesn't need to be prime!)e: BigInt withkregisters
Outputs:
- Returns BigInt
out = a^e (mod p).
Assumptions:
- Assumes
k <= 50andk * n <= 500.
Implementation:
- A small optimization is to compute the bit length of
efirst, and then do the square-and-multiply method as a loop on the bit length.
Parameters:
a: BigInt withkregistersp: a prime BigInt withkregisters
Outputs:
- Returns BigInt with
kregistersout = a^{-1} (mod p). Returns0ifa = 0.
Assumptions:
- Assumes
k <= 50andk * n <= 500.
Implementation:
- Uses Fermat's Little Theorem and computes
out = a^{p-2} (mod p).
fp.circom contains templates for operating on elements of F_p. See Fp element for a reminder on how an element of F_p is represented. By default, an F_p element means a proper BigInt with k registers of bit size n. Unless explicitly stated, we do not constrain elements to be < p.
The templates all take a parameter p, which is a length k array representing p in proper BigInt format with bit size n registers.
Input:
in:F_pelement
Output:
out:-in (mod p) = p - inifin != 0, else0.
Circuit constrains in <= p .
Inputs:
in: signed overflow representation withkregisters with absolute value< 2^overflowX: signed overflow representation withmregisters with absolute value< 2^{overflow - n - log(min(k,m)) - 1}Y:F_pelement
Implements:
- Constrain
in = p * X + Y. UsesCheckCarryToZero.
Assumptions:
- Assume
overflow < 251 - Assume
overflow - 1 >= n.
Inputs:
in: signed overflow representation withkregisters with absolute value< 2^overflow
Outputs:
X: signed overflow representation withceil(overflow / n)registers in[-2^n, 2^n)out:F_pelement such thatin = p * X + outas integers.
Implements:
- Witnesses for
X, outare precomputed. The witness foroutsatisfiesout < p. - Constrain
in === p * X + outusingCheckCarryModP. Does not constrainout < p.
Assumptions:
- Input registers have absolute value
< 2^overflow n + 1 <= overflow < 251
Input:
a,b:F_pelements
Output:
out:F_pelement congruent toa * b (mod p).
Implementation:
- We first prove a computation of
a * bas an overflow BigInt representation with2k-1registers usingBigMultShortLong. - We "compress" the above computation to a congruent representation
mod pwithkregisters usingPrimeReduce. This is an optimization for the next step. - We use
SignedFpCarryModPto generate a witnessoutand constrain thatout = a * b (mod p).
Assumption:
k^2 * 2^{3n} < 251
Constrains that the input is congruent to 0 (mod p). The method is the same as SignedFpCarryModP except we save constraints by not having to range check out = 0.
Input:
in: signed overflow BigInt representation withkregisters- Assume
in[i]has absolute value< 2^overflow
Output:
Xis signed overflow BigInt withceil(overflow / n)registers in[-2^n, 2^n)such thatin = p * Xas integers.
Assumption:
overflow < 251
This is a proof of computation of sgn0 as described in the IRTF draft.
Input:
in:F_pelement
Output:
out = sgn0(in)is0or1.
Implementation:
sgn0(in) = in % 2.- Constrains
in < psince the formula forsgn0assumes this.
Input:
in:F_pelement
Output:
out = (in == 0 ? 1 : 0)
Implementation:
- Constrains
in < pand then checks ifin = 0as BigInt.
Input:
in[0], in[1]: twoF_pelements
Output:
out = (in[0] == in[1])
Implementation:
- Constrains
in[0] < pandin[1] < pand then checks if they are equal as BigInts.
fp2.circom contains templates for operating on elements of F_{p^2}. See Fp2 element for a reminder on how an element of F_{p^2} is represented. Unless explicitly stated, we do not constrain the corresponding F_p elements to be < p.
Inputs:
a = a[0] + a[1] uwherea[i]is signed overflow representation withkaregisters.b = b[0] + b[1] uwhereb[i]is signed overflow representation withkbregisters
Output:
out = out[0] + out[1] uwhereout[i]is signed overflow representation withka + kb - 1registers such thatout = a * binZ[u]/(u^2 + 1)(Zdenotes integers).
Implementation:
- Uses
BigMultShortLongUnequalto multiplya * bwithout carries. - Uses the identity
u^2 = -1. - Despite the naming, does not involve any prime
p. - If
a[i][j], b[i][j]all have absolute value< B, thenout[i][j]has absolute value< 2k * B^2.
Assumptions:
- Assume
2 * k * B^2 < 2^252wherea[i][j], b[i][j] < Bfor alli,j.
Parameter m_out is passed when calling template with the expected max number of bits in the output registers.
Calls SignedFp2MultiplyNoCarryUnequal(n, k, k, m_out).
Inputs:
in = in[0] + in[1] uwherein[i]is signed overflow representation withk + mregisters.
Output:
out = out[0] + out[1] uwhereout[i]is signed overflow representation withkregistersout[i] = in[i] (mod p)
Implementation:
- Calls
PrimeReducetwice. - If
in[i][j]all have absolute value< B, thenout[i][j]has absolute value< (m+1) * 2^n * B.
Assumptions:
- Assume
(m+1) * 2^n * B < 2^252
Parameter m_out is passed when calling template with the expected max number of bits in the output registers.
Inputs:
a = a[0] + a[1] uwherea[i]is signed overflow representation withkregisters.b = b[0] + b[1] uwhereb[i]is signed overflow representation withkregisters
Output:
out = out[0] + out[1] uwhereout[i]is signed overflow representation withkregistersoutis equal toa * bas elements inF_{p^2}
Implementation:
- Combines
SignedFp2MultiplyNoCarryandFp2Compress. - If
a[i][j], b[i][j]all have absolute value< B, thenout[i][j]has absolute value< 2k^2 * 2^n * B^2.
Parameters:
m_in: expected max number of bits in the input registers (soB = 2^{m_in})m_out: expected max number of bits in the output registers (so2k^2 * 2^{n + 2*m_in} <= 2^{m_out})
Inputs:
a = a[0] + a[1] uwherea[i]is signed overflow representation withkregisters.b = b[0] + b[1] uwhereb[i]is signed overflow representation withkregistersc = c[0] + c[1] uwherec[i]is signed overflow representation withkregisters
Output:
out = out[0] + out[1] uwhereout[i]is signed overflow representation withkregistersoutis equal toa * b * cas elements inF_{p^2}
Implementation:
- Calls
SignedFp2MultiplyNoCarrytwice to computea * band(a * b) * cand then appliesFp2Compresstoa * b * c. - If
a[i][j], b[i][j], c[i][j]all have absolute value< B, thenout[i][j]has absolute value< 4k^2 * (2k-1) * 2^n * B^3.
Parameters:
m_in: expected max number of bits in the input registers (soB = 2^{m_in})m_out: expected max number of bits in the output registers (so4k^2 * (2k-1) * 2^{n + 3*m_in} <= 2^{m_out})
Inputs:
in: length2 x karray of integers
Implements:
- Proves that
0 <= in[i][j] < 2^nfor alli,j. In other words,in[0], in[1]are proper BigInt representations.
Input:
in = in[0] + in[1] uwherein[i]is signed overflow representation withkregisters
Outputs:
X = X[0] + X[1] uwhereX[i]is signed overflow representation withceil(overflow / n)registers in[-2^n, 2^n)out:F_{p^2}elementout = out[0] + out[1] usuch thatin[i] = p * X[i] + out[i]as integers.
Implements:
- Calls
SignedFpCarryModPtwice. - We do not constrain
out[i] < p.
Assumptions:
- Input registers have absolute value
< 2^overflow n + 1 <= overflow < 251
Inputs:
a,b:F_{p^2}elements
Output:
out:F_{p^2}element such thatout = a * binF_{p^2}
Implements:
- Combines
SignedFp2MultiplyNoCarryCompressandSignedFp2CarryModP - We do not constrain
out[i] < p.
Assumptions:
- All BigInts are in proper format, i.e., registers in
[0, 2^n) 2k^2 * 2^{3n} < 2^251
Inputs:
a,b,c:F_{p^2}elements
Output:
out:F_{p^2}element such thatout = a * b * cinF_{p^2}
Implements:
- Combines
SignedFp2MultiplyNoCarryCompressThreeandSignedFp2CarryModP - We do not constrain
out[i] < p.
Assumptions:
- All BigInts are in proper format, i.e., registers in
[0, 2^n) 4k^2 * (2k-1) * 2^{4n} < 2^251
Input:
in:F_{p^2}element
Output:
out:F_{p^2}elementout = (p - in[0]) + (p - in[1]) usoout = -ininF_{p^2}
Implementation:
- Constrains
0 <= in[0], in[1] <= p - Calls
FpNegatetwice
Input:
in:F_{p^2}element
Output:
out:F_{p^2}element equal toin^{-1}
Implementation:
- Precompute witness for
in^{-1}usingfind_Fp2_inversehelper function - Constrain
out * in == 1inF_{p^2}usingFp2Multiply
Assumptions:
2k^2 * 2^{3n} < 2^251
Inputs:
a = a[0] + a[1] uwherea[i]are signed overflow representations withkregistersb = b[0] + b[1] uwhereb[i]are signed overflow representations withkregisters
Output:
out:F_{p^2}element equal toa / binF_{p^2}.
Assumptions:
- Registers of
ahave absolute value< 2^overflowa - Registers of
bhave absolute value< 2^overflowb k + ceil(overflowa / n) <= 502k + ceil(overflowb / n) <= 50overflowa < 2502k^2 * 2^{2n + overflowb} < 2^250
Input:
in:F_{p^2}element
Output:
out:F_{p^2}element equal to conjugate ofinout = in[0] - in[1] u
Input:
in:F_{p^2}element
Output:
out:F_{p^2}element equal toin^{p^power}
Implements:
- Conjugates
inifpoweris odd,out = inifpoweris even.
Assumption:
p = 3 (mod 4)so thata - b u = (a + b u)^p
This is a proof of computation of sgn0 as described in the IRTF draft.
Input:
in:F_{p^2}element
Output:
out = sgn0(in)is either0or1
Implementation:
sgn0(in) = sgn0(in[0]) || ( in[0] == 0 && sgn0(in[1]) )- Calls
FpSgn0twice, in the process constrainsin[0], in[1] < p
Input:
in:F_{p^2}element
Output:
out = (in == 0)
Implementation:
- Constrains
in[0], in[1] < pand then checks ifin[0] == 0 && in[1] == 0.
Input:
a, b:F_{p^2}elements
Output:
out = (a == b)
Implementation:
- Constrains
a[i], b[i] < pand then checks ifa[i] == b[i]as BigInts fori=0,1
fp12.circom contains templates for operating on elements of F_{p^12}. See Fp12 element for a reminder on how an element of F_{p^12} is represented. Unless explicitly stated, we do not constrain the corresponding F_p elements to be < p.
This circuit computes power applications of the Frobenius map (i.e., raising to p-th power). It is specialized to p = q the BLS12-381 base field modulus, due to the need to precompute Frobenius coefficients.
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^{p^power}
Implementation:
- We follow the methodology from this paper and @noble/bls12-381
- We load values for
FP12_FROBENIUS_COEFFICIENTSprecomputed in Python.
Assumption:
- Assume
p = 1 (mod 6)
Inputs:
a: BigInt in signed overflow representation withkaregisters.b = sum_{i=0}^5 sum_{j=0}^1 b[i][j] w^i u^jwhereb[i][j]is signed overflow representation withkbregisters
Output:
out = sum_{i=0}^5 sum_{j=0}^1 out[i][j] w^i u^jwhereout[i][j]is signed overflow representation withka + kb - 1registersout = a * bas12-dimensional vector with integer coefficients
Implementation:
- Uses
BigMultShortLongUnequalto multiplyout[i][j] = a * b[i][j]without carries. - If input registers all have absolute value
< B, thenout[i][j]has absolute value< min(ka, kb) * B^2.
Assumption:
- Assume
min(ka, kb) * B^2 < 2^252.
Parameter m_out is passed when calling template with the expected max number of bits in the output registers.
Calls SignedFp12ScalarMultiplyNoCarryUnequal(n, k, k, m_out).
Inputs:
a = a[0] + a[1] uwherea[i]is signed overflow representation withkaregisters.b = sum_{i=0}^5 sum_{j=0}^1 b[i][j] w^i u^jwhereb[i][j]is signed overflow representation withkbregisters
Output:
out = sum_{i=0}^5 sum_{j=0}^1 out[i][j] w^i u^jwhereout[i][j]is signed overflow representation withka + kb - 1registersout = a * binF_{p^12}as overflow representations
Implementation:
- Multiplies
out[i] = a * b[i]as inSignedFp2MultiplyNoCarryusingu^2 = -1. - If input registers all have absolute value
< B, thenout[i][j]has absolute value< 2*min(ka, kb) * B^2.
Assumption:
- Assume
2*min(ka, kb) * B^2 < 2^252.
Parameter m_out is passed when calling template with the expected max number of bits in the output registers.
Calls SignedFp12Fp2MultiplyNoCarryUnequal(n, k, k, m_out).
Inputs:
a = sum_{i=0}^5 sum_{j=0}^1 a[i][j] w^i u^jwherea[i][j]is signed overflow representation withkaregistersb = sum_{i=0}^5 sum_{j=0}^1 b[i][j] w^i u^jwhereb[i][j]is signed overflow representation withkbregisters
Output:
out = sum_{i=0}^5 sum_{j=0}^1 out[i][j] w^i u^jwhereout[i][j]is signed overflow representation withka + kb - 1registersout = a * binF_{p^12}as overflow representations
Implementation:
- Write
a = a[][0] + a[][1] uandb = b[][0] + b[][1] u. - Prove computation of
a * b = (a[][0] * b[][0] - a[][1] * b[][1]) + (a[][0] * b[][1] + a[][1] * b[][0]) uusing identityu^2 = -1.- Prove computation of
a[][i] * b[][j]as polynomials in two variablesw, XusingBigMultShortLong2DUnequalwhereXis variable for2^n.
- Prove computation of
- Result is polynomial of degree
10inwand degreeka + kb - 2inX. - Use identity
w^6 = 1 + uto turn into degree5polynomial inw - If input registers all have absolute value
< B, thenout[i][j]has absolute value< 18*min(ka, kb) * B^2.
Assumption:
- Assume
18*min(ka, kb) * B^2 < 2^252.
Parameter m_out is passed when calling template with the expected max number of bits in the output registers.
Calls SignedFp12MultiplyNoCarryUnequal(n, k, k, m_out)
Inputs:
in = sum_{i=0}^5 sum_{j=0}^1 in[i][j] w^i u^jwherein[i][j]is signed overflow representation withk + mregisters
Outputs:
out = sum_{i=0}^5 sum_{j=0}^1 out[i][j] w^i u^jwhereout[i][j]is signed overflow representation withkregisters
Implements:
- Calls
PrimeReduce12times. - If all input registers have absolute value
< B, then output registers have absolute value< (m+1) * 2^n * B.
Assumption:
(m+1) * 2^n * B < 2^252
Inputs:
a = sum_{i=0}^5 sum_{j=0}^1 a[i][j] w^i u^jwherea[i][j]is signed overflow representation withkregistersb = sum_{i=0}^5 sum_{j=0}^1 b[i][j] w^i u^jwhereb[i][j]is signed overflow representation withkregisters
Output:
out = sum_{i=0}^5 sum_{j=0}^1 out[i][j] w^i u^jwhereout[i][j]is signed overflow representation withkregistersout = a * binF_{p^12}as overflow representations
Implementation:
- Combines
SignedFp12MultiplyNoCarryandFp12Compress. - If all input registers have absolute value
< B, then output registers have absolute value< 18k^2 * 2^n * B^2
Assumption:
18k^2 * 2^n * B^2 < 2^252
Inputs:
in = sum_{i=0}^5 sum_{j=0}^1 in[i][j] w^i u^jwherein[i][j]is signed overflow representation withkregisters
Outputs:
X = sum_{i=0}^5 sum_{j=0}^1 X[i][j] w^i u^jwhereX[i][j]is signed overflow representation withceil(overflow / n)registers in[-2^n, 2^n)out: properF_{p^12}elementin = p * X + outinZ[u,w]/(u^2 + 1, w^6 - (1+u)).
Implements:
- Calls
SignedFpCarryModP12times. - We do not constrain
out[i][j] < p.
Assumptions:
- Input registers have absolute value
< 2^overflow n + 1 <= overflow < 251
Inputs:
a,b:F_{p^12}elements
Output:
out:F_{p^12}element such thatout = a * binF_{p^12}
Implements:
- Combines
SignedFp12MultiplyNoCarryCompressandSignedFp12CarryModP - We do not constrain
out[i][j] < p.
Assumptions:
- All BigInts are in proper format, i.e., registers in
[0, 2^n) 18k^2 * 2^{3n} < 2^251
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^{-1}
Implementation:
- Precompute witness for
in^{-1}usingfind_Fp12_inversehelper function - Constrain
out * in == 1inF_{p^12}usingFp12Multiply
Assumptions:
18k^2 * 2^{3n} < 2^251
field_elements_func.circom contains helper functions for witness generation involving field operations in F_p, F_{p^2}, F_{p^12}. Unless otherwise specified, all representations are in proper BigInt format with k registers of bit size n, and corresponding F_p elements are < p.
Parameter:
a:F_pelement
Output:
- Returns
a % 2
This is never used anywhere. Did not empirically lead to faster witness generation times versus Fermat's Little Theorem.
Parameter:
num:F_pelement
Output:
- Returns
num^{-1}asF_pelement using extended Euclidean algorithm.
Parameter:
a: BigInt in signed overflow representation withkregisters
Output:
- Return
outas length2 x 50array out[0]hasmregisters in range[-2^n, 2^n)out[1]isF_pelement withkregisters,0 <= out[1] < pa = p * out[0] + out[1]soout[1] = a (mod p)
Assumptions:
- Assume actual integer value of
ahas absolute value< 2^{n*(k+m)} k + m <= 50
Parameter:
a: length2 x karray witha[i]in signed overflow representation withkregisters
Output:
- Return
outas length2 x 2 x 50array out[i] = a[i] (mod p)by callingget_signed_Fp_carry_witnesstwice
Assumptions:
- Assume actual integer value of
a[i]has absolute value< 2^{n*(k+m)} k + m <= 50
Parameter:
a:F_{p^2}element
Output:
- Returns
sgn0(a[0]) || (a[0] == 0 && sgn0(a[1]))
Parameters:
a,b:F_{p^2}elements
Output:
- Return
a * bas properF_{p^2}element
Parameters:
a,b:F_{p^2}elements
Output:
- Return
a + bas properF_{p^2}element
Parameters:
a,b:F_{p^2}elements
Output:
- Return
a - bas properF_{p^2}element
Parameters:
a:F_{p^2}elemente: proper BigInt representation with2kregisters
Output:
- Return
a^eas properF_{p^2}element
Implementation:
- Small optimization to compute bit length of
efirst before running square-and-multiply loop on the bit length.
Assumption:
- Assume
k * n <= 400
Parameters:
a,b:F_{p^2}elements
Output:
- Returns
a == b
This is a macro.
Parameter:
a = a[0] + a[1] uwitha[i]signed overflow representations.
Output:
- Returns
a * (XI0 + u)inZ[u]/(u^2 + 1).
Parameters:
a,b:F_{p^12}elements
Output:
- Returns
a + bas properF_{p^12}element
Parameters:
a,b:F_{p^12}elements
Output:
- Returns
a - bas properF_{p^12}element
Parameters:
a,b:F_{p^12}elements
Output:
- Returns
a * bas properF_{p^12}element
Parameters:
a:F_{p^2}element
Output:
- Returns
a^{-1}as properF_{p^2}element - Uses fact that
(a + b u)^{-1} = (a^2 + b^2)^{-1} * (a - b u)and reduces to compute anF_pinverse.
This is only used as an intermediary to find inverses in F_{p^12}.
Parameters:
a0, a1, a2:F_{p^2}elements- Consider
a = a0 + a1 v + a2 v^2asF_{p^6}element, wherev = w^2andv^3 = 1 + u.
Output:
- Returns
a^{-1}inF_{p^6}as a properF_{p^12}representation (length6 x 2 x karray) - Computed by solving a system of equations with
F_{p^2}coefficients.
Parameters:
a:F_{p^12}element
Output:
- Return
a^{-1}as properF_{p^12}element - Write
a = a0 + a1 wand use fact that(a0 + a1 w) * (a0 - a1 w) = a0^2 - a1^2 vis an element inF_{p^6}, wherev = w^2, to reduce to finding inverses inF_{p^6}.
curve.circom contains circuits for operations on F_p points of an elliptic curve. Most of the circuits work for an arbitrary elliptic curve E in short Weierstrass form y^2 = x^3 + a x + b where a,b are "short" integers, i.e., < 2^n. For optimization purposes and simplicity, a few circuits only work for curves of the form y^2 = x^3 + b (i.e., a = 0), but can be easily modified to work in the case a != 0 if further need arises.
See Point in E(F_p) for a reminder on how we represent points in E(F_p). Unless otherwise specificied, all BigInts use k registers of bit size n. Unless explicitly stated, we do not constrain a point in E(F_p) to actually lie on the curve.
Prove that three points (x_0, y_0), (x_1, y_1), (x_2, -y_2) are co-linear.
Input:
in: length3 x 2 x karray within[i][j]element ofF_p
Implementation:
- Let
in[i] = (x_i, y_i). - Proves that
(y_0 + y_2) * (x_1 - x_0) - (y_1 - y_0) * (x_0 - x_2) == 0 (mod p). (y_0 + y_2) * (x_1 - x_0) - (y_1 - y_0) * (x_0 - x_2)is computed "without carry" usingBigMultShortLongand then compressed usingPrimeReduce.- Use
SignedCheckCarryModToZeroto prove congruence to0 (mod p).
Assumption:
in[0] != in[1]- Requires
8k^2 * 2^{3n} < 2^251to prevent overflow
Prove that a point (x,y) lies on an elliptic curve y^2 = x^3 + a x + b.
Input:
in: length2 x karray representing twoF_pelements
Implementation:
- Let
in = (x,y). - Proves that
x^3 + a x + b - y^2 = 0 (mod p). - Computes
x^3 + a x + b - y^2without carries usingBigMultShortLongand then compresses usingPrimeReduce. - Use
SignedCheckCarryModToZeroto prove congruence to0 (mod p).
Assumptions:
- Curve parameters
0 <= a,b < 2^n - Requires
(k^2 + 1) * (2k-1) * 2^{4n} < 2^251to prevent overflow.
Prove that a point (x_3, -y_3) lies on the tangent line to curve E : y^2 = x^3 + a x + b at a point (x_1, y_1). Does not check that (x_1, y_1) is on the curve. Note that the circuit does not require b.
Input:
in: length2 x 2 x karray representing fourF_pelements
Implementation:
- Let
in[0] = (x_1, y_1)andin[1] = (x_3, y_3). - Proves that
2y_1 (y_1 + y_3) = (3 x_1^2 + a)(x_1 - x_3).
Assumptions:
- Curve parameter
0 <= a < 2^n in[0]is onE(F_p)- Require
(3k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 5k(2k - 1) <= 2^n
Verify the computation of addition of two points P1 + P2 on an elliptic curve E : y^2 = x^3 + a1 x + b1 assuming that P1 != P2 and P1 != -P2. We do not verify these assumptions and do not check that P1, P2 actually lie on the curve. Note that the circuit does not require knowledge of curve parameters a1, b1.
Inputs:
a: point onE(F_p)b: point onE(F_p)
Output:
out: point onE(F_p)equal toa + busing elliptic curve addition.
Implementation:
- Let
a = (x_1, y_1), b = (x_2, y_2), out = (x_3, y_3). - Precomputes witness for
outand then proves that: (x_1 + x_2 + x_3)*(x_2 - x_1)^2 = (y_2 - y_1)^2(y_1 + y_3)*(x_2 - x_1) = (y_2 - y_1)*(x_1 - x_3)usingPointOnLine
Assumptions:
a, bare onE(F_p)x_1 != x_2, i.e.,a != banda != -b.- Require
(3k^2(2k-1) + 1) * 2^{4n} < 2^251to prevent overflow. k(2k-1) <= 2^n
Verify the computation of doubling a point on the elliptic curve E : y^2 = x^3 + a x + b. We do not check that the point actually lies on the curve.
Inputs:
in: point onE(F_p)
Output:
out: point onE(F_p)equal to2 * inusing elliptic curve doubling formula.
Implementation:
- Let
in = (x_1, y_1), out = (x_3, y_3). - Precomputes witness for
outand then proves that: (x_3, y_3)lies onEusingPointOnCurve(x_3, y_3)is on the tangent line toEat(x_1, y_1)usingPointOnTangentx_1 != x_3: the only points of intersection of the tangent line at(x_1, y_1)with curveEare(x_1, y_1)and(x_3, y_3).
Assumptions:
- Curve parameters
0 <= a, b < 2^n inlies onE(F_p)y_1 != 0, i.e.,inis not a point of order2. (Fact: BLS12-381 has no points of order2.)- Require
(3k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 5k(2k - 1) <= 2^n
Verify the computation of addition of two points P1 + P2 on an elliptic curve E : y^2 = x^3 + a1 x + b1 without any assumptions on P1, P2. Moreover, we allow P1, P2 to be the point at infinity.
We do not check that P1, P2 actually lie on the curve. Due to the deterministic nature of circom, this circuit costs the sum of the constraints of EllipticCurveAddUnequal and EllipticCurveDouble.
Inputs:
a: point onE(F_p)aIsInfinity:1if we should interpretaas point at infinity;0otherwiseb: point onE(F_p)bIsInfinity:1if we should interpretbas point at infinity;0otherwise
Output:
out: point onE(F_p)equal toa + busing elliptic curve addition.isInfinity:1ifa + bis point at infinity;0otherwise- If
a,bare onE(F_p)(even ifaIsInfinity == 1), thenoutis onE(F_p)(even ifisInfinity == 1)
Implementation:
- Proves computations of both
EllipticCurveAddUnequalandEllipticCurveDouble - Case analysis of
a = b,a = -b,a, bequal point at infinity
Assumptions:
a, bare onE(F_p)E(F_p)has no points of order2- Require
(3k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 5k(2k - 1) <= 2^n
Proves computation of scalar multiplication [x]P on elliptic curve of form E : y^2 = x^3 + b using the double-and-add method.
Parameter:
x: integer in[0, 2^250)to scalar multiply by
Inputs:
in: point onE(F_p)inIsInfinity:1ifinshould be interpreted as point at infinity;0otherwise
Outputs:
out: point onE(F_p)equal to[x]PwhereP = inisInfinity:1ifoutshould be interpreted as point at infinity;0otherwise- Assuming
inis a point onE(F_p)(even wheninIsInfinity == 1),outis a point onE(F_p)(even whenisInfinity == 1).
Implementation:
- Double-and-add method. Uses
EllipticCurveAddin the "add" part since we cannot guarantee we are adding two unequal points.
Assumptions:
0 <= x < 2^250inis point onE(F_p)even ifinIsInfinity == 1E(F_p)has no points of order2- Require
(3k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 5k(2k - 1) <= 2^n
Proves computation of scalar multiplication [x]P on elliptic curve of form E : y^2 = x^3 + b using the double-and-add method, assuming that P has order > x so we never arrive at the point at infinity and we are always adding unequal points.
Parameter:
x: integer in[0, 2^250)to scalar multiply by
Inputs:
in: point onE(F_p)
Outputs:
out: point onE(F_p)equal to[x]PwhereP = in.
Implementation:
- Double-and-add method. Uses
EllipticCurveAddUnequalin the "add" part because ifPhas order> x, then[i]P != [j]Pfor any0 < i,j <= x.
Assumptions:
0 <= x < 2^250inis point onE(F_p)of order> xE(F_p)has no points of order2- Require
(3k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 5k(2k - 1) <= 2^n
Proves evaluation of a line through two unequal E(F_p) points at a E(F_{p^12}) point, evaluated without carries.
Inputs:
P: twoE(F_p)pointsP[0], P[1]Q: a point inE(F_{p^12})
Output:
out: an element inF_{p^12}without[i][j]in signed overflow representation with2k-1registers
Implementation:
- Let
P[0] = (x_1, y_1), P[1] = (x_2, y_2)andQ = (X, Y). out = (y_1 - y_2) X + (x_2 - x_1) Y + (x_1 y_2 - x_2 y_1)- We evaluate
outusingSignedFp12ScalarMultiplyNoCarry - If all input registers are in
[0, B), then output registers have absolute value< 3k * B^2
Assumptions:
P[0] != P[1]3k * B^2 < 2^252
Parameter m_out is the expected max number of bits in the output registers.
Proves evaluation of a tangent line to curve E : y^2 = x^3 + b through an E(F_p) point P at a E(F_{p^12}) point Q, evaluated without carries.
Inputs:
P:E(F_p)pointQ:E(F_{p^12})point
Output:
out: an element inF_{p^12}without[i][j]in signed overflow representation with3k-2registers
Implementation:
- Let
P = (x, y)andQ = (X, Y). out = 3 x^2 (-X + x) + 2 y (Y - y)- We evaluate
outusingSignedFp12ScalarMultiplyNoCarry - If all input registers are in
[0, B), then output registers have absolute value< (3k^2 + 2k/B) * B^3assuming2k <= B
Assumptions:
(3k^2 + 2k/B) * B^3 < 2^252
Proves evaluation of a line through two unequal E(F_p) points at a E(F_{p^12}) point.
Inputs:
P: twoE(F_p)pointsP[0], P[1]Q:E(F_{p^12})point
Output:
out:F_{p^12}element equal tol_{P[0], P[1]}(Q)
Implementation:
- Calls
SignedLineFunctionUnequalNoCarry, then compresses usingFp12Compress, and finally carries usingSignedFp12CarryModP
Assumptions:
P[0] != P[1]- Requires
3k^2 * 2^{3n} < 2^251to prevent overflow.
Proves evaluation of a tangent line to curve E : y^2 = x^3 + b through an E(F_p) point P at a E(F_{p^12}) point Q.
Inputs:
P:E(F_p)pointQ:E(F_{p^12})point
Output:
out:F_{p^12}element equal tol_{P,P}(Q)
Implementation:
- Calls
SignedLineFunctionEqualNoCarry, then compresses usingFp12Compress, and finally carries usingSignedFp12CarryModP
Assumptions:
- Requires
(3k^2(2k-1) + 1) * 2^{4n} < 2^251to prevent overflow. - Assumes
2k(2k - 1) <= 2^n
Inputs:
g: element ofF_{p^12}in signed overflow format withkgregistersP: twoE(F_p)pointsQ:E(F_{p^12})point
Output:
out:F_{p^12}element equal tog * l_{P[0], P[1]}(Q)
Implementation:
- Calls
SignedLineFunctionUnequalNoCarryto computel_{P[0], P[1]}(Q) - Calls
SignedFp12MultiplyNoCarryUnequalto computeg * l_{P[0], P[1]}(Q)all without carries - Compresses using
Fp12Compressand finally carries just once usingSignedFp12CarryModP
Assumptions:
P[0] != P[1]- Requires
3k * min(kg, 2k-1) * 18 * (k + kg - 1) * 2^{overflowg + 3n} < 2^251to prevent overflow. (In practicekg = kandoverflowg = n.)
The point is that l_{P[0], P[1]}(Q) is quadratic, so we can squeeze in another multiplication before we need to carry. This is used in MillerLoop.
Proves computation of Miller's algorithm on a curve of the form y^2 = x^3 + b. Only used for the Tate pairing.
Parameters:
b: curve parameterx: integer
Inputs:
in:F_{p^12}elementP:E(F_p)pointQ:E(F_{p^12})point
Outputs:
out:F_{p^12}elementxP:E(F_p)point equal to[x]P
Implementation:
out = f_x(P, Q)wheref_i(P,Q)is defined recursively using Miller's algorithm:f_0(P,Q) = inf_{i+j}(P,Q) = f_i(P,Q) * f_j(P,Q) * l_{[i]P, [j]P}(Q)
f_x(P, Q)and[x]Pare computed using the double-and-add method.
Assumptions:
0 <= b < 2^n0 <= x < 2^250Plies onE(F_p)Phas order> xandPis not point at infinity- Requires
(18k)^2 * (2k-1) * 2^{4n} < 2^251to prevent overflow
Proves computation of Miller's algorithm on the curve BLS12-381 for the Tate pairing.
Inputs:
P:E(F_p)pointQ:E(F_{p^12})point
Output:
out:F_{p^12}element equal tof_r(P, Q)whereris the prime order of torsion in Tate pairing
Implementation:
- Uses the specific form of
r = x^4 - x^2 + 1wherexis parameter of BLS12-381, 64-bit integer with low Hamming weight - Calls
MillerLoopfour times
Assumptions:
Plies onE(F_p)Phas orderr(but we do not constrain this) whereris primePis not point at infinity- Requires
(18k)^2 * (2k-1) * 2^{4n} < 2^251to prevent overflow
curve_fp2.circom contains circuits for operations on F_{p^2} points of an elliptic curve. These circuits are almost entirely parallel to those in curve.circom (see Elliptic curve templates).
Most of the circuits work for an arbitrary elliptic curve E_2 in short Weierstrass form y^2 = x^3 + a x + b where a,b are "short" F_{p^2} points (e.g., a = a[0] + a[1] u with 0 <= a[0], a[1] < 2^n). For optimization purposes and simplicity, a few circuits only work for curves of the form y^2 = x^3 + b (i.e., a = 0), but can be easily modified to work in the case a != 0 if further need arises.
See Point in E_2(F_{p^2}) for a reminder on how we represent points in E_2(F_{p^2}). Unless otherwise specificied, all BigInts use k registers of bit size n. Unless explicitly stated, we do not constrain a point in E_2(F_{p^2}) to actually lie on the curve.
Prove that three points (x_0, y_0), (x_1, y_1), (x_2, -y_2) are co-linear.
Input:
in: length3 x 2 x 2 x karray within[i][j]element ofF_{p^2}
Implementation:
- Let
in[i] = (x_i, y_i). - Proves that
(y_0 + y_2) * (x_1 - x_0) - (y_1 - y_0) * (x_0 - x_2) == 0inF_{p^2}. (y_0 + y_2) * (x_1 - x_0) - (y_1 - y_0) * (x_0 - x_2)is computed "without carry" usingBigMultShortLong2Dand then compressed usingPrimeReduce.- Use
SignedCheckCarryModToZeroto prove congruence to0 (mod p).
Assumption:
in[0] != in[1]- Requires
6k^2 * 2^{3n} < 2^251to prevent overflow
Prove that a point (x,y) lies on an elliptic curve y^2 = x^3 + a x + b.
Parameters:
a,b: length2arrays
Input:
in: length2 x 2 x karray representing twoF_{p^2}elements
Implementation:
- Let
in = (x,y). - Proves that
x^3 + a x + b - y^2 == 0inF_{p^2}. - Computes
x^3 + a x + b - y^2without carries usingSignedFp2MultiplyNoCarryUnequaland then compresses usingPrimeReduce. - Use
SignedCheckCarryModToZeroto prove congruence to0 (mod p).
Assumptions:
- Curve parameters
0 <= a[i],b[i] < 2^nfori=0,1 - Requires
((4k^2(2k-1) + 1) * 2^{4n} < 2^251to prevent overflow. 2k^2 + 2(2k-1) <= 2^n
Prove evaluation of x^3 + a x + b for input x.
Parameters:
a,b: length2arrays
Input:
in:F_{p^2}element
Output:
out:F_{p^2}element equal toin^3 + a * in + b
Assumptions:
- Curve parameters
0 <= a[i],b[i] < 2^nfori=0,1 - Requires
(4k^2(2k-1) + 1) * 2^{4n} < 2^251to prevent overflow. 2k - 1 <= 2^n
Prove that a point (x_3, -y_3) lies on the tangent line to curve E_2 : y^2 = x^3 + a x + b at a point (x_1, y_1). Does not check that (x_1, y_1) is on the curve. Note that the circuit does not require b.
Parameter:
a: length2array
Input:
in: length2 x 2 x 2 x karray representing fourF_{p^2}elements
Implementation:
- Let
in[0] = (x_1, y_1)andin[1] = (x_3, y_3). - Proves that
2y_1 (y_1 + y_3) = (3 x_1^2 + a)(x_1 - x_3)inF_{p^2}.
Assumptions:
- Curve parameters
0 <= a[0], a[1] < 2^n in[0]is onE_2- Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 12k(2k - 1) <= 2^n
Verify the computation of addition of two points P1 + P2 on an elliptic curve E_2 : y^2 = x^3 + a2 x + b2 assuming that P1 != P2 and P1 != -P2. We do not verify these assumptions and do not check that P1, P2 actually lie on the curve. Note that the circuit does not require knowledge of curve parameters a2, b2.
Inputs:
a: point onE_2(F_{p^2})b: point onE_2(F_{p^2})
Output:
out: point onE_2(F_{p^2})equal toa + busing elliptic curve addition.
Implementation:
- Let
a = (x_1, y_1), b = (x_2, y_2), out = (x_3, y_3). - Precomputes witness for
outand then proves that: (x_1 + x_2 + x_3)*(x_2 - x_1)^2 = (y_2 - y_1)^2inF_{p^2}(y_1 + y_3)*(x_2 - x_1) = (y_2 - y_1)*(x_1 - x_3)usingPointOnLineFp2
Assumptions:
a, bare onE_2x_1 != x_2, i.e.,a != banda != -b.- Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 2k(2k - 1) <= 2^n
Verify the computation of doubling a point on the elliptic curve E_2 : y^2 = x^3 + a x + b. We do not check that the point actually lies on the curve.
Parameters:
a,b: length2arrays
Inputs:
in: point onE_2(F_{p^2})
Output:
out: point onE_2(F_{p^2})equal to2 * inusing elliptic curve doubling formula.
Implementation:
- Let
in = (x_1, y_1), out = (x_3, y_3). - Precomputes witness for
outand then proves that: (x_3, y_3)lies onE_2usingPointOnCurveFp2(x_3, y_3)is on the tangent line toE_2at(x_1, y_1)usingPointOnTangentFp2x_1 != x_3: the only points of intersection of the tangent line at(x_1, y_1)with curveE_2are(x_1, y_1)and(x_3, y_3).
Assumptions:
- Curve parameters
0 <= a[i], b[i] < 2^nfori = 0,1. inlies onE_2y_1 != 0, i.e.,inis not a point of order2. (Fact: BLS12-381 twistE_2has no points of order2.)- Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 12k(2k - 1) <= 2^n
Verify the computation of addition of two points P1 + P2 on an elliptic curve E_2 : y^2 = x^3 + a2 x + b2 without any assumptions on P1, P2. Moreover, we allow P1, P2 to be the point at infinity.
We do not check that P1, P2 actually lie on the curve. Due to the deterministic nature of circom, this circuit costs the sum of the constraints of EllipticCurveAddUnequalFp2 and EllipticCurveDoubleFp2.
Inputs:
a: point onE_2(F_{p^2})aIsInfinity:1if we should interpretaas point at infinity;0otherwiseb: point onE_2(F_{p^2})bIsInfinity:1if we should interpretbas point at infinity;0otherwise
Output:
out: point onE_2(F_{p^2})equal toa + busing elliptic curve addition.isInfinity:1ifa + bis point at infinity;0otherwise- If
a,bare onE_2(even ifaIsInfinity == 1), thenoutis onE_2(even ifisInfinity == 1)
Implementation:
- Proves computations of both
EllipticCurveAddUnequalFp2andEllipticCurveDoubleFp2 - Case analysis of
a = b,a = -b,a, bequal point at infinity
Assumptions:
a, bare onE_2E_2(F_{p^2})has no points of order2- Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 12k(2k - 1) <= 2^n
Proves computation of scalar multiplication [x]P on elliptic curve of form E_2 : y^2 = x^3 + b using the double-and-add method.
Parameter:
b: length2arrayx: integer in[0, 2^250)to scalar multiply by
Inputs:
in: point onE_2(F_{p^2})inIsInfinity:1ifinshould be interpreted as point at infinity;0otherwise
Outputs:
out: point onE_2(F_{p^2})equal to[x]PwhereP = inisInfinity:1ifoutshould be interpreted as point at infinity;0otherwise- Assuming
inis a point onE_2(even wheninIsInfinity == 1),outis a point onE_2(even whenisInfinity == 1). - Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 12k(2k - 1) <= 2^n
Implementation:
- Double-and-add method. Uses
EllipticCurveAddFp2in the "add" part since we cannot guarantee we are adding two unequal points.
Assumptions:
0 <= x < 2^250inis point onE_2even ifinIsInfinity == 1E_2(F_{p^2})has no points of order2
Proves computation of scalar multiplication [x]P on elliptic curve of form E_2 : y^2 = x^3 + b using the double-and-add method, assuming that P has order > x so we never arrive at the point at infinity and we are always adding unequal points.
Parameter:
b: length2arrayx: integer in[0, 2^250)to scalar multiply by
Inputs:
in: point onE_2(F_{p^2})
Outputs:
out: point onE_2(F_{p^2})equal to[x]PwhereP = in.
Implementation:
- Double-and-add method. Uses
EllipticCurveAddUnequalFp2in the "add" part because ifPhas order> x, then[i]P != [j]Pfor any0 < i,j <= x.
Assumptions:
0 <= x < 2^250inis point onE_2of order> xE_2(F_{p^2})has no points of order2- Require
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 12k(2k - 1) <= 2^n
Proves evaluation of a line through two unequal E_2(F_{p^2}) points at a E(F_p) point, evaluated without carries. To give this circuit meaning, we implicitly assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Inputs:
P: twoE_2(F_{p^2})pointsP[0], P[1]Q:E(F_p)point
Output:
out: an element inF_{p^12}without[i][j]in signed overflow representation with2k-1registers
Implementation:
- Let
P[0] = (x_1, y_1), P[1] = (x_2, y_2)andQ = (X, Y). out = w^3 (y_1 - y_2) X + w^4 (x_2 - x_1) Y + w (x_1 y_2 - x_2 y_1)- We evaluate
outusingSignedFp2MultiplyNoCarryand optimize using the knowledge that1, w, ..., w^5is aF_{p^2}-basis forF_{p^12}. - If all input registers are in
[0, B), then output registers have absolute value< 2k * B^2
Assumptions:
P[0] != P[1]2k * B^2 < 2^252
Parameter m_out is the expected max number of bits in the output registers.
Proves evaluation of a tangent line to curve E_2 : y^2 = x^3 + b through an E_2(F_{p^2}) point P at a E(F_p) point Q, evaluated without carries. To give this circuit meaning, we implicitly assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Inputs:
P:E_2(F_{p^2})pointQ:E(F_p)point
Output:
out: an element inF_{p^12}without[i][j]in signed overflow representation with3k-2registers
Implementation:
- Let
P = (x, y)andQ = (X, Y). out = (3x^3 - 2y^2) + w^2 (-3 x^2 X) + w^3 (2 y Y)- We evaluate
outusingSignedFp2MultiplyNoCarryUnequaland optimize using the knowledge that1, w, ..., w^5is aF_{p^2}-basis forF_{p^12}. - If all input registers are in
[0, B), then output registers have absolute value< (12k^2 + 4k/B) * B^3
Assumptions:
Pis onE_2(12k^2 + 4k/B) * B^3 < 2^252
Proves evaluation of a line through two unequal E_2(F_{p^2}) points at a E(F_p) point. To give this circuit meaning, we implicitly assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Inputs:
P: twoE_2(F_{p^2})pointsP[0], P[1]Q:E(F_p)point
Output:
out:F_{p^12}element equal tol_{Psi(P[0]), Psi(P[1])}(Q)
Implementation:
- Calls
SignedLineFunctionUnequalNoCarryFp2, then compresses usingFp12Compress, and finally carries usingSignedFp12CarryModP
Assumptions:
P[0] != P[1]- Requires
2k^2 * 2^{3n} < 2^251to prevent overflow.
Proves evaluation of a tangent line to curve E_2 : y^2 = x^3 + b through an E_2(F_{p^2}) point P at a E(F_p) point Q. To give this circuit meaning, we implicitly assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Inputs:
P:E_2(F_{p^2})pointQ:E(F_p)point
Output:
out:F_{p^12}element equal tol_{Psi(P), Psi(P)}(Q)
Implementation:
- Calls
SignedLineFunctionEqualNoCarryFp2, then compresses usingFp12Compress, and finally carries usingSignedFp12CarryModP
Assumptions:
Pis onE_2- Requires
(12k^2(2k - 1) + 1) * 2^{4n} < 2^251to prevent overflow. 4k(2k-1) <= 2^n
Inputs:
g: element ofF_{p^12}in signed overflow format withkgregistersP: twoE_2(F_{p^2})pointsQ:E(F_p)point
Output:
out:F_{p^12}element equal tog * l_{Psi(P[0]), Psi(P[1])}(Q)
Implementation:
- Calls
SignedLineFunctionUnequalNoCarryFp2to computel_{Psi(P[0]), Psi(P[1])}(Q) - Calls
SignedFp12MultiplyNoCarryUnequalto computeg * l_{Psi(P[0]), Psi(P[1])}(Q)all without carries - Compresses using
Fp12Compressand finally carries just once usingSignedFp12CarryModP
Assumptions:
P[0] != P[1]- Requires
12k * min(kg, 2k-1) * 18 * (k + kg - 1) * 2^{overflowg + 3n} < 2^251to prevent overflow. (In practicekg = kandoverflowg = n.)
The point is that l_{Psi(P[0]), Psi(P[1])}(Q) is quadratic, so we can squeeze in another multiplication before we need to carry. This is used in MillerLoopFp2.
Proves computation of Miller's algorithm on a curve of the form y^2 = x^3 + b. Used for the optimal Ate pairing. We assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Parameters:
b: length2arrayx: integer
Inputs:
P:E_2(F_{p^2})pointQ:E(F_p)point
Outputs:
out:F_{p^12}elementxP:E(F_p)point equal to[x]P
Implementation:
out = f_x(P, Q)wheref_i(P,Q)is defined recursively using Miller's algorithm:f_0(P,Q) = 1f_{i+j}(P,Q) = f_i(P,Q) * f_j(P,Q) * l_{Psi([i]P), Psi([j]P)}(Q)
f_x(P, Q)and[x]Pare computed using the double-and-add method.
Assumptions:
0 <= b[0], b[1] < 2^n0 <= x < 2^250Pis onE_2Phas order> xandPis not point at infinity- Requires
(18k)^2 * (2k-1) * 2^{4n} < 2^251to prevent overflow
Proves computation of running Miller's algorithm twice on a curve of the form y^2 = x^3 + b. Used for BLS signatures. We assume that E_2 is a sextic twist of E, and we are embedding E_2(F_{p^2}) into E(F_{p^12}) using the twist homomorphism Psi(x,y) = (x/w^2, y/w^3).
Parameters:
b: length2arrayx: integer
Inputs:
P: twoE_2(F_{p^2})pointsP[0], P[1]Q: twoE(F_p)pointsQ[0], Q[1]
Outputs:
out:F_{p^12}element equal tof_x(P[0], Q[0]) * f_x(P[1], Q[1])
Implementation:
out = f_x(P[0], Q[0]) * f_x(P[1], Q[1])wheref_i(P,Q)is defined recursively using Miller's algorithm:f_0(P,Q) = 1f_{i+j}(P,Q) = f_i(P,Q) * f_j(P,Q) * l_{Psi([i]P), Psi([j]P)}(Q)
- We use the double-and-add method with an optimization that we only need to keep track of the product
f_i(P[0], Q[0]) * f_i(P[1], Q[1]). This means we only need to square once inF_{p^12}instead of twice.
Assumptions:
0 <= b[0], b[1] < 2^n0 <= x < 2^250P[0], P[1]are onE_2P[i]has order> xandP[i]is not point at infinity fori = 0,1.- Requires
(18k)^2 * (2k-1) * 2^{4n} < 2^251to prevent overflow
final_exp.circom contains circuits for exponentiating an F_{p^12} element to the (p^12 - 1)/r power, which is necessary for the Tate pairing and optimal Ate pairing. The exponentiation can be separated into two parts: an easy part utilizing Frobenius maps and a hard part.
For the hard part we use the approach of Hayashida-Hayasaka-Teruya. The hard part involves exponentiating an element in the cyclotomic subgroup, and we optimize this by using the optimization for cyclotomic squaring of Karabina.
The cyclotomic subgroup of F_{p^12} is defined as the subgroup of all elements a such that a^{q^4 - q^2 + 1} = 1, where q^4 - q^2 + 1 is the 12th cyclotomic polynomial.
Theorem 3.1 of Karabina shows that an element in the cyclotomic subgroup can be recovered (decompressed) from data in a compressed format. This circuit verifies the compression step.
Input:
in:F_{p^12}element
Output:
out: fourF_{p^2}elements
Implementation:
- Let
in = g0 + g2 w + g4 w^2 + g1 w^3 + g3 w^4 + g5 w^5whereg_iareF_{p^2}elements. out = [g2, g3, g4, g5]
Assumption:
inis in the cyclotomic subgroup
This circuit verifies the decompression step mentioned above.
Input:
in: fourF_{p^2}elements
Output:
out:F_{p^12}element
Implementation:
- Let
in = [g2, g3, g4, g5] - If
g2 != 0:(g5^2 * (1+u) + 3 g4^2 - 2 g3)/(4g2)(2 g1^2 + g2 * g5 - 3 g3*g4) * (1+u) + 1
- If
g2 == 0:g1 = (2 g4 * g5)/g3g0 = (2 g1^2 - 3 g3 * g4) * (1+u) + 1
- Uses
SignedFp2Divide out = [g0, g2, g4, g1, g3, g5]
Assumptions:
- Require
(10k^2 + 1) * 2^{3n} < 2^250to prevent overflow
Theorem 3.2 of Karabina gives a formula for how to square a cyclotomic element in its compressed form. This circuit verifies the computation where no carries are performed.
Input:
in: fourF_{p^2}elements
Output:
out: fourF_{p^2}elements with BigInts in signed overflow representation with2k - 1registers
Implementation:
- Let
c = 1 + u h2 = 2(g2 + 3*c*B_45)h3 = 3(A_45 - (c+1)B_45) - 2g3h4 = 3(A_23 - (c+1)B_23) - 2g4h5 = 2(g5 + 3B_23)A_ij = (g_i + g_j)(g_i + c g_j)B_ij = g_i g_jout = [h2, h3, h4, h5]- All operations are done without carrying.
- If all input registers have absolute value
< B, then output registers have absolute value< (54k + 2/B) * B^2
Assumption:
(54k + 2/B) * B^2 < 252
Verifies computation of cyclotomic squaring in compressed form with carries.
Input:
in: fourF_{p^2}elements
Output:
out: fourF_{p^2}elements
Implementation:
- Calls
SignedFp12CyclotomicSquareNoCarryand then four calls toFp2CompressandSignedFp2CarryModP
Assumption:
- Requires
(54k^2 + 1) * 2^{3n} < 251to prevent overflow.
Circuit verifies computation of exponentiation of cyclotomic element to e power.
Parameter:
e: positive integer
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^e
Implementation:
- We exponentiate using the square-and-multiply method.
- Compress
inat the beginning and compute squares in compressed format. - Decompress and multiply at the bits equal to
1ine
Assumptions:
0 < e < BabyJubJubPrimeinis in the cyclotomic subgroup- Require
(10k^2 + 1) * 2^{3n} < 2^250to prevent overflow
This circuit is specialized to BLS12-381 as it uses the parameter x generating BLS curves. It uses the approach of Hayashida-Hayasaka-Teruya, top of p. 14.
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^{(p^4 - p^2 + 1)/r}
Assumptions:
0 < e < BabyJubJubPrimeinis in the cyclotomic subgroup- Require
(10k^2 + 1) * 2^{3n} < 2^250to prevent overflow
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^{(p^6 - 1)(p^2+1)}
Implementation:
- Uses
Fp12FrobeniusMap
Assumption:
18k^2 * 2^{3n} < 2^251
This circuit is specialized to BLS12-381.
Input:
in:F_{p^12}element
Output:
out:F_{p^12}element equal toin^{(p^12 - 1)/r}
Implementation:
- Combines
FinalExpEasyPartandFinalExpHardPart.
Assumption:
(10k^2 + 1) * 2^{3n} < 2^250
bls12_381_hash_to_G2.circom contains circuits for proving computations that hash a message to the subgroup G2 of E_2(F_{p^2}), the twist of BLS12-381. These are in accordance with the IRTF Internet draft. The implementation is rather technical so we refer to the code for details.
bls12_381_hash_to_G2.circom also contains optimized circuits for proving that input elements lie in the subgroups G1 of BLS12-381 E(F_p) and G2 of E_2(F_{p^2}) its twist. These use the method of endomorphisms.
Implements steps 2-6 of hash_to_curve as specified in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#section-3 for BLS12-381.
Input:
in: twoF_{p^2}elements
Output:
out:E_2(F_{p^2})point that lies in subgroupG2isInfinity:1ifoutshould be interpreted as point at infinity;0otherwise
In practice in = hash_to_field(msg, 2) for an arbitrary-length byte string msg, in which case out = hash_to_curve(msg).
Input:
in: pair ofF_{p^2}elements
Implements:
- Proves that
inis a point onE_2(F_{p^2}), the twist of BLS12-381 - Proves that
inhas orderr, i.e.,inis in subgroupG2
Input:
in: pair ofF_pelements
Implements:
- Proves that
inis a point on BLS12-381E(F_p) - Proves that
inhas orderr, i.e.,inis in subgroupG1
pairing.circom contains the circuits for the Tate pairing and optimal Ate pairing, specialized to BLS12-381.
Input:
P:E(F_p)elementQ:E(F_{p^12})element
Output:
out:F_{p^12}element equal to Tate pairinge(P,Q)
Assumption:
Pis onEand has orderrQis onE
Input:
P:E_2(F_{p^2})element whereE_2is twist of BLS12-381Q:E(F_p)element
Output:
out:F_{p^12}element equal to optimal Ate pairinge(P,Q)
Assumption:
Pis onE_2and has orderrQis onE
bls_signature.circom contains the circuits for BLS signature verification, specialized to BLS12-381.
Circuit to verify BLS signature where public key size is minimized (so public key is in subgroup G1) and we are given the hash H(m) of a message as a point in subgroup G2.
Inputs:
pubkey:E(F_p)pointsignature:E_2(F_{p^2})pointHm:E_2(F_{p^2})point
Output:
out:1if valid BLS signature;0otherwise
Implementation:
- Checks if
e(g1, signature) == e(pubkey, H(m))by checking ife(g1, signature) * e(pubkey, -H(m)) == 1wheree(,)is the optimal Ate pairing,g1is a fixed public generator ofG1. - Computes
e(g1, signature) * e(pubkey, -H(m))by callingMillerLoopFp2Twoand thenFinalExponentiate.
Assumptions:
pubkeyis onEand in subgroupG1signatureis onE_2and in subgroupG2Hmis onE_2and in subgroupG2
Circuit to verify BLS signature where public key size is minimized (so public key is in subgroup G1) and we are given a hashed message in the form of two F_{p^2} elements (in practice, hash = hash_to_field(msg,2)).
Inputs:
pubkey: length2 x karraysignature: length2 x 2 x karrayhash: length2 x 2 x karray
Implements:
- Verifies that
pubkey,signature,hashhave entries in[0, 2^n) - Verifies that
pubkeyis point onE(F_p)- Proves that each
F_pcoordinate is< p - Proves that
pubkeylies onE
- Proves that each
- Verifies that
pubkeyis in subgroupG1 - Verifies that
signatureis point onE_2(F_{p^2})- Proves that each
F_pcoordinate is< p - Proves that
signaturelies onE_2
- Proves that each
- Verifies that
signatureis in subgroupG2 - Verifies that
hash[i][j] < pfor0 <= i,j < 2sohashis a pair ofF_{p^2}elements. - Verifies that
e(g1, signature) == e(pubkey, H(m))whereH(m) = MapToG2(hash).