Point halving in Secp256k1 - the others are similar.
Let $P = [\frac a 2]G$ i.e. we have $[2]P = [a]G = Q$. In words, $P$ is the halfpoint of $Q$.
Let $P = (p_x,q_x)$ and $Q = (q_x,q_x)$
We may expect that it has two solutions $$P =\big[\frac{a}{2}\big]G =\big[\frac{a + q}{2}\big] G \left(= \big[\frac{a}{2}\big] G + \big[\frac{ q}{2}\big] G \right), $$ however, the base point $G$ of the Bitcoin curve has odd order;
int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
115792089237316195423570985008687907853269984665640564039457584007908834671663
Therefore, if there exists half of a point then it is unique.
- The derivative of the equation $y^2 = x^3 + 7$
$\lambda = \dfrac{3x^{2}}
{2(x^{3} + 7)^{1/2}} \tag{1} \label{r1}$
- Write down the equation for the tangent line to $E$ at G:
$$y-p_y = \lambda(x-p_x) => y = \lambda(x - p_x) + p_y \tag{2}$$
- Write the equation for the intersection of the tangent line with E:
$$y^{2} = (\lambda(x - p_x) + p_y)^{2} = x^{3} + 7 \tag{3}\label{r3}$$
Write down $\lambda$ in terms of $p_x$:
If we extend the equation \ref{r3}, we will get a monic cubic polynomial, so the coefficient of $x^2$ will be minus the sum of the roots (Vieta's Formula ($-b/a$)), and the leading coefficient is 1.
\begin{align}
x^{3} + 7 & = (\lambda (x - p_x) + p_y)^{2} \\
x^{3} + 7 & = \lambda^2 (x - p_x)^2 + 2 \lambda (x - p_x) p_y + p_y^{2} \\
x^{3} + 7 & = \lambda^2 (x^2 - 2 x p_x + p_x^2) + 2 \lambda x p_y - 2 \lambda p_x p_y + p_y^{2} \\
0 &= x^{3} + 7 - \lambda^2 (x^2 - 2 x p_x + p_x^2) - 2 \lambda x p_y + 2 \lambda p_x p_y - p_y \\
0 &= x^{3} \color{red}{- \lambda^2 x^2} + \lambda^2 2 x p_x - \lambda^2 p_x^2 - 2 \lambda x p_y + 2 \lambda p_x p_y - p_y^{2} + 7\\
0 &= x^{3} \color{red}{- \lambda^2 x^2} + (\lambda^2 2 p_x - 2 \lambda p_y)x + (- \lambda^2 p_x^2 + 2 \lambda p_x p_y - p_y^{2} + 7)\\
\end{align}
as we can see the term for $x^2$ is $- \lambda^2$. Since the roots are the intersection point then $p_x$ will be a double point and $q_x$ will be a single point, by Vieata's formula $$\lambda^2 = 2 p_x + q_x \label{r4}\tag{4}$$
Form equation using equation \ref{r4} and and replacing $x$ with $p_x$ in the equation \ref{r1};
$$\lambda^{2} = 2p_x + q_x = \frac{9p_x^{\,4}}{4(p_x^{\,3} + 7)} \tag{5} \label{r5}$$
Simplify this equation and move everything over to the left-hand side will yield $$ (2p_x + q_x)(4(p_x^{\,3} + 7)) = 9p_x^{\,4}\\ -p_x^4 + 4 p_x^3 q_x + 56 p_x + 28 q_x= 0$$
a quartic polynomial in $p_x$. The roots of this polynomial are the x-coordinates of the half points of $G$. We are in the odd case, the factors of the quartic polynomial will be a linear equation and an irreducible resolvent cubic.
The validation with SageMath
#Secp256K1 prime
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
#Secp256K1 order
q = 115792089237316195423570985008687907852837564279074904382605163141518161494337
#One of the roots
t = 82764486716702815285605477501188164702466527314352175978120539775788537185277
print("Expected root ", t)
#define ring of polynomials
R.<x> = PolynomialRing(GF(p),'x')
x-coordinate of Q where Q = [2]P
qx = Integer(84538659774007663836420160802839342215744092791779235474817172502887599548487)
#From equation (5)
g = (2 x + qx)(4(x^3+7)) - (3x^2)^2
gRoots = g.roots()
print("The roots of quartic = ", gRoots)
gEvalAt_t = ((2 t + qx)(4(t^3+7)) - (3t^2)^2 ) % p
print( "gg(t) =", gEvalAt_t)
Outputs
Expected root 82764486716702815285605477501188164702466527314352175978120539775788537185277
The roots of quartic = [(82764486716702815285605477501188164702466527314352175978120539775788537185277, 1)]
gg(t) = 0
Try, online on SageMathCell
Note that this is a single test.