def lift_x(x: int) -> Non-obligatory[Point]:
It is a operate that given an X coordinate, computes one of many two corresponding Y coordinates on the curve; particularly, the even one.
Each doable worth within the subject of coordinates (integers modulo p, the place p = 2256 – 232 – 977) has precisely 0 factors on the curve y2 = x3 + 7, or precisely two. In case there are two factors with a given X coordinate, the corresponding Y coordinates might be one another’s negation (modulo p), and one might be even, and one might be odd. This lift_x operate returns the one with the even Y.
y_sq = (pow(x, 3, p) + 7) % p #<-the curve
This computes y_sq = y2, utilizing the truth that it equals x3 + 7 (mod p), utilizing the curve equation.
y = pow(y_sq, (p + 1) // 4, p) # why is that this __floordiv__ 4?
This computes the sq. root y of the worth y_sq we decided within the earlier now. On the whole, modular sq. roots could be computed utilizing the Tonelli-Shanks algorithm, however for the secp256k1 modulus, this algorithm merely boils all the way down to computing y_sq(p+1)/4 mod p. In Python, we have to write this (p+1)/4 as (p+1)//4
as a result of we would like precise integer arithmetic. (p+1)/4
would compute an approximate floating level quantity solely.
if pow(y, 2, p) != y_sq:
return None
This verifies whether or not the computed worth y is definitely the modular sq. root of y_sq. If the enter x worth was not a legitimate X coordinate on the curve, then x3 + 7 will not be a sq., and thus will not have a sq. root. Nevertheless, the components y_sq(p+1)/4 at all times yields a end result, even when y_sq would not have a sq. root. So we have to examine whether or not y2 = y_sq. If not, we return None
instantly: the enter X has no corresponding Y coordinates.
return (x, y if y & 1 == 0 else p-y) # make y odd if there's a sqrt?
This merely negates y (modulo p) if y is odd, thereby discovering the opposite (even) answer. This ensures returning the even Y coordinate out of the 2 options.