def miller_loop(Q: Point2D[FQ12], P: Point2D[FQ12]) -> FQ12: if Q is None or P is None: return FQ12.one() R = Q # type: Point2D[FQ12] f = FQ12.one() for i in range(log_ate_loop_count, -1, -1): f = f * f * linefunc(R, R, P) R = double(R) if ate_loop_count & (2**i): f = f * linefunc(R, Q, P) R = add(R, Q) # assert R == multiply(Q, ate_loop_count) Q1 = (Q[0]**field_modulus, Q[1]**field_modulus) # assert is_on_curve(Q1, b12) nQ2 = (Q1[0]**field_modulus, -Q1[1]**field_modulus) # assert is_on_curve(nQ2, b12) f = f * linefunc(R, Q1, P) R = add(R, Q1) f = f * linefunc(R, nQ2, P) # R = add(R, nQ2) This line is in many specifications but it technically does nothing return f**((field_modulus**12 - 1) // curve_order)
m = 3 * x1**2 / (2 * y1) return m * (xt - x1) - (yt - y1) else: return xt - x1 def cast_point_to_fq12(pt: Point2D[FQ]) -> Point2D[FQ12]: if pt is None: return None x, y = pt fq12_point = (FQ12([x.n] + [0] * 11), FQ12([y.n] + [0] * 11)) return fq12_point # Check consistency of the "line function" one, two, three = G1, double(G1), multiply(G1, 3) negone, negtwo, negthree = ( multiply(G1, curve_order - 1), multiply(G1, curve_order - 2), multiply(G1, curve_order - 3), ) assert linefunc(one, two, one) == FQ(0) assert linefunc(one, two, two) == FQ(0) assert linefunc(one, two, three) != FQ(0) assert linefunc(one, two, negthree) == FQ(0) assert linefunc(one, negone, one) == FQ(0) assert linefunc(one, negone, negone) == FQ(0) assert linefunc(one, negone, two) != FQ(0) assert linefunc(one, one, one) == FQ(0) assert linefunc(one, one, two) != FQ(0)