# Elliptic curve operations for incredulous
[Wikipedia](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication) and other materials typically hide all the intermediate steps, so we have to derive them ourseleves to understand how it works under the hood.
## Point addition
$P + Q + R = 0\ where\ P\ne Q\ne R$
Curve equation (Weierstrass form):
$y^2 = x^3 + ax + b$
Our line defined by $P$ and $Q$:
$y = \lambda x + \beta$
Let's go:
$\lambda^2x^2 + 2\lambda x + \beta^2 = x^3 + ax + b$
$x^3 - \lambda^2x^2 + (a - 2\lambda)x + (b - \beta^2) = 0$
Roots of cubic polynomial $ax^3 + bx^2 + cx + d$ (Vieta's theorem):
$p + q + r = - b/a$
$pq + qr + rp = c/a$
$pqr = - d/a$
So in our case:
$x_p + x_q + x_r = - (- \lambda^2) = \lambda^2$
$x_r = \lambda^2 - x_p - x_q$
Where:
$\lambda = \dfrac{y_q - y_p}{x_q-x_p}$
Picking the $y$ that is not on the line:
$\beta = y_p - \lambda x_p$
$y_r = -(\lambda x_r + \beta)$
$y_r = \lambda (x_p - x_r) - y_p$
Reference implementation: https://github.com/ethereum/py_pairing/blob/e95dece17e5d948e62b1492b05ba88b726aa25e6/py_ecc/bn128/bn128_curve.py#L46
NOTE that this also works for cases when either $P$ or $Q$ are tangent points.
### In projective coordinates
Context https://hackmd.io/@cailynyongyong/HkuoMtz6o#Projective-Coordinates
Goal: avoid modular division (finding multiplicative inverse).
Curve equation in projective space:
$y^2z=x^3 + axz^2 + bz^3$
Point transformation:
$P' = (x_p',y_p',z_p) = (x_pz, y_pz, z)$
$Q' = (x_q',y_q',z_q) = (x_qz, y_qz, z)$
Upon conversion from Affine coordinates $z = 1$, but then it can change.
Trick: transform $y_r, x_r$ into fractions having the same denominator, which is effectively $z_r$.
Let's convert our prior addition formulas from affine to projective space:
$\lambda = \dfrac{y_q-y_p}{x_q-x_p} = \dfrac{y_q'/z_q - y_p'/z_p}{x_q'/z_q - x_p'/z_p} = \dfrac{y_q'z_p - y_p'z_q}{x_q'z_p - x_p'z_q}$
Calculating intermediate results:
$u_q = y_q'z_p$
$u_p = y_p'z_q$
$v_q = x_q'z_p$
$v_p = x_p'z_q$
$u = u_q - u_p$
$v = v_q - v_p$
$w = z_pz_q$
$\lambda = u/v$
Now let's expand and simplify:
$x_r = \lambda^2 - x_p - x_q = \dfrac{u^2}{v^2} - x_p'/z_p - x_q'/z_q = \dfrac{u^2w - v^2(v_p + v_q)}{v^2w}$
$y_r = \lambda (x_p - x_r) - y_p = \dfrac{u}{v}(x_p'/z_p - x_r) - y_p'/z_p = \dfrac{uv(v_p - x_rw) - v^2u_p}{v^2w}$
Making substitutions and converging to the same denominator:
$y_r = \dfrac{uv^2v_p - u^2w + v^2(v_p+v_q) - v^3u_p}{v^3w}$
$x_r = \dfrac{u^2wv - v^3(v_p + v_q)}{v^3w}$
Also recalling that:
$x_r = x_r'/z_r$ and $y_r = y_r'/z_r$
It means that:
$x_r' = v(u^2w - v^2(v_p + v_q))$
$y_r' = v^2(uv_p - vu_p) - (u^2w - v^2(v_p+v_q))$
$z_r = v^3w$
Simplifying further:
$t = u^2w - v^2(v_p + v_q)$
$x_r' = vt$
$y_r' = v^2(uv_p - vu_p) - t$
$z_r = v^3w$
NOTE that you might find different letters/representations in various places, the main idea is to minimize the total number of additions/multiplications and reuse intermediate results as much as possible.
### In Jacobian coordinates
### In quadratic extension
## Point doubling
$P + Q + R = 0\ where\ P == Q\ is\ a\ tangent\ point$
Rewriting our curve equation as a function of two variables:
$f(x,y) = y^2 - x^3 - ax - b$
The slope of the tangent is $dy/dx$, but we will use implicit differentiation since our function is defined as $f(x, y) = 0$:
$dy/dx = -\dfrac{df/dx}{df/dy}$
Applying chain rule:
$dy/dx = -\dfrac{-3x^2 - a}{2y}$
Evaluating at the known point:
$\lambda = \dfrac{3x_p + a}{2y_p}$
Then we can reuse formulas obtained previously:
$x_r = \lambda^2 - 2x_p$
$y_r = \lambda (x_p - x_r) - y_p$
Reference implementation: https://github.com/ethereum/py_pairing/blob/e95dece17e5d948e62b1492b05ba88b726aa25e6/py_ecc/bn128/bn128_curve.py#L38
### In projective coordinates
How we can determine that $P = Q$ or $P+Q=O$ in projective coordinates?
Instead of checking that $x_p'/z_p=x_q'/z_q$ and $y_p'/z_p = y_q'/z_q$ we can cross multiply and get:
$x_q'z_p-x_p'z_q=v=0$
$y_q'z_p-y_p'z_q=u=0$ for the case $P=Q$
$y_q'z_p+y_p'z_q=u_q+u_p=0$ for the case $P+Q=O$
Now let's adapt doubling formulas for the projective space:
$\lambda = \dfrac{3x_p + a}{2y_p} = \dfrac{3x_p'/z_p + a}{2y_p'/z_p} = \dfrac{3x_p' + az_p}{2y_p'}$
$u = (3x_p' + az_p)z_p$
$v = 2y_p'z_p$
$\lambda = \dfrac{u}{v}$
We have additionally multiplied by $z_p$ so that later we can have a common denominator:
$x_r = \lambda^2 - 2x_p = \dfrac{u^2 - 2x_p'4y_p'^2z_p}{v^2} = \dfrac{u^2 - 2x_p'y_p'v}{v^2}$
$t = 2x_p'y_p'v$
$s = u^2 - t$
After replacements and adjustments:
$x_r = \dfrac{vs}{v^3}$
$y_r = \lambda (x_p - x_r) - y_p = \dfrac{ux_p'}{vz_p} - \dfrac{us}{v^3} - \dfrac{y_p'}{z_p} = \dfrac{2uvx_p'y_p' - us - 2v^2y_p'^2}{v^3} = \dfrac{u(t - s) - 2v^2y_p'^2}{v^3}$
Therefore:
$x_r'=vs$
$y_r'=u(t-s) - 2v^2y_p'^2$
$z_r=v^3$
## Twist
Frobenius endomorphism = maps every element to it's $p$-th power
||Non-invertible|Invertible|
|-|-|-|
|Structure-preserving mapping (function)|[Homo]morphism|Isomorphism|
| Morphism of an object to itself |Endomorphism|Automorphism|