Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1# Prover implementation for Weierstrass curves of the form2# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws3# operating on affine and Jacobian coordinates, including the point at infinity4# represented by a 4th variable in coordinates.6load("group_prover.sage")9class affinepoint:10def __init__(self, x, y, infinity=0):11self.x = x12self.y = y13self.infinity = infinity14def __str__(self):15return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity)18class jacobianpoint:19def __init__(self, x, y, z, infinity=0):20self.X = x21self.Y = y22self.Z = z23self.Infinity = infinity24def __str__(self):25return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity)28def point_at_infinity():29return jacobianpoint(1, 1, 1, 1)32def negate(p):33if p.__class__ == affinepoint:34return affinepoint(p.x, -p.y)35if p.__class__ == jacobianpoint:36return jacobianpoint(p.X, -p.Y, p.Z)37assert(False)40def on_weierstrass_curve(A, B, p):41"""Return a set of zero-expressions for an affine point to be on the curve"""42return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'})45def tangential_to_weierstrass_curve(A, B, p12, p3):46"""Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)"""47return constraints(zero={48(p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve'49})52def colinear(p1, p2, p3):53"""Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear"""54return constraints(zero={55(p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1',56(p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2',57(p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3'58})61def good_affine_point(p):62return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'})65def good_jacobian_point(p):66return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'})69def good_point(p):70return constraints(nonzero={p.Z^6 : 'nonzero_X'})73def finite(p, *affine_fns):74con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'})75if p.Z != 0:76return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con)77else:78return con80def infinite(p):81return constraints(nonzero={p.Infinity : 'infinite_point'})84def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC):85"""Check whether the passed set of coordinates is a valid Jacobian add, given assumptions"""86assumeLaw = (good_affine_point(pa) +87good_affine_point(pb) +88good_jacobian_point(pA) +89good_jacobian_point(pB) +90on_weierstrass_curve(A, B, pa) +91on_weierstrass_curve(A, B, pb) +92finite(pA) +93finite(pB) +94constraints(nonzero={pa.x - pb.x : 'different_x'}))95require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) +96colinear(pa, pb, negate(pc))))97return (assumeLaw, require)100def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC):101"""Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions"""102assumeLaw = (good_affine_point(pa) +103good_affine_point(pb) +104good_jacobian_point(pA) +105good_jacobian_point(pB) +106on_weierstrass_curve(A, B, pa) +107on_weierstrass_curve(A, B, pb) +108finite(pA) +109finite(pB) +110constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'}))111require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) +112tangential_to_weierstrass_curve(A, B, pa, negate(pc))))113return (assumeLaw, require)116def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC):117assumeLaw = (good_affine_point(pa) +118good_affine_point(pb) +119good_jacobian_point(pA) +120good_jacobian_point(pB) +121on_weierstrass_curve(A, B, pa) +122on_weierstrass_curve(A, B, pb) +123finite(pA) +124finite(pB) +125constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'}))126require = infinite(pC)127return (assumeLaw, require)130def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC):131assumeLaw = (good_affine_point(pa) +132good_affine_point(pb) +133good_jacobian_point(pA) +134good_jacobian_point(pB) +135on_weierstrass_curve(A, B, pb) +136infinite(pA) +137finite(pB))138require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'}))139return (assumeLaw, require)142def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC):143assumeLaw = (good_affine_point(pa) +144good_affine_point(pb) +145good_jacobian_point(pA) +146good_jacobian_point(pB) +147on_weierstrass_curve(A, B, pa) +148infinite(pB) +149finite(pA))150require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'}))151return (assumeLaw, require)154def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC):155assumeLaw = (good_affine_point(pa) +156good_affine_point(pb) +157good_jacobian_point(pA) +158good_jacobian_point(pB) +159infinite(pA) +160infinite(pB))161require = infinite(pC)162return (assumeLaw, require)165laws_jacobian_weierstrass = {166'add': law_jacobian_weierstrass_add,167'double': law_jacobian_weierstrass_double,168'add_opposite': law_jacobian_weierstrass_add_opposites,169'add_infinite_a': law_jacobian_weierstrass_add_infinite_a,170'add_infinite_b': law_jacobian_weierstrass_add_infinite_b,171'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab172}175def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):176"""Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field"""177F = Integers(p)178print("Formula %s on Z%i:" % (name, p))179points = []180for x in range(0, p):181for y in range(0, p):182point = affinepoint(F(x), F(y))183r, e = concrete_verify(on_weierstrass_curve(A, B, point))184if r:185points.append(point)187ret = True188for za in range(1, p):189for zb in range(1, p):190for pa in points:191for pb in points:192for ia in range(2):193for ib in range(2):194pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia)195pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib)196for branch in range(0, branches):197assumeAssert, assumeBranch, pC = formula(branch, pA, pB)198pC.X = F(pC.X)199pC.Y = F(pC.Y)200pC.Z = F(pC.Z)201pC.Infinity = F(pC.Infinity)202r, e = concrete_verify(assumeAssert + assumeBranch)203if r:204match = False205for key in laws_jacobian_weierstrass:206assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC)207r, e = concrete_verify(assumeLaw)208if r:209if match:210print(" multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity))211else:212match = True213r, e = concrete_verify(require)214if not r:215ret = False216print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e))218print()219return ret222def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC):223assumeLaw, require = f(A, B, pa, pb, pA, pB, pC)224return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require)226def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):227"""Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically"""228R.<ax,bx,ay,by,Az,Bz,Ai,Bi> = PolynomialRing(QQ,8,order='invlex')229lift = lambda x: fastfrac(R,x)230ax = lift(ax)231ay = lift(ay)232Az = lift(Az)233bx = lift(bx)234by = lift(by)235Bz = lift(Bz)236Ai = lift(Ai)237Bi = lift(Bi)239pa = affinepoint(ax, ay, Ai)240pb = affinepoint(bx, by, Bi)241pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai)242pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi)244res = {}246for key in laws_jacobian_weierstrass:247res[key] = []249print("Formula " + name + ":")250count = 0
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.