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.
1load("secp256k1_params.sage")3MAX_ORDER = 10005# Set of (curve) orders we have encountered so far.6orders_done = set()8# Map from (subgroup) orders to [b, int(gen.x), int(gen.y), gen, lambda] for those subgroups.9solutions = {}11# Iterate over curves of the form y^2 = x^3 + B.12for b in range(1, P):13# There are only 6 curves (up to isomorphism) of the form y^2 = x^3 + B. Stop once we have tried all.14if len(orders_done) == 6:15break17E = EllipticCurve(F, [0, b])18print("Analyzing curve y^2 = x^3 + %i" % b)19n = E.order()21# Skip curves with an order we've already tried22if n in orders_done:23print("- Isomorphic to earlier curve")24print()25continue26orders_done.add(n)28# Skip curves isomorphic to the real secp256k129if n.is_pseudoprime():30assert E.is_isomorphic(C)31print("- Isomorphic to secp256k1")32print()33continue35print("- Finding prime subgroups")37# Map from group_order to a set of independent generators for that order.38curve_gens = {}40for g in E.gens():41# Find what prime subgroups of group generated by g exist.42g_order = g.order()43for f, _ in g.order().factor():44# Skip subgroups that have bad size.45if f < 4:46print(f" - Subgroup of size {f}: too small")47continue48if f > MAX_ORDER:49print(f" - Subgroup of size {f}: too large")50continue52# Construct a generator for that subgroup.53gen = g * (g_order // f)54assert(gen.order() == f)56# Add to set the minimal multiple of gen.57curve_gens.setdefault(f, set()).add(min([j*gen for j in range(1, f)]))58print(f" - Subgroup of size {f}: ok")60for f in sorted(curve_gens.keys()):61print(f"- Constructing group of order {f}")62cbrts = sorted([int(c) for c in Integers(f)(1).nth_root(3, all=true) if c != 1])63gens = list(curve_gens[f])64sol_count = 065no_endo_count = 067# Consider all non-zero linear combinations of the independent generators.68for j in range(1, f**len(gens)):69gen = sum(gens[k] * ((j // f**k) % f) for k in range(len(gens)))70assert not gen.is_zero()71assert (f*gen).is_zero()73# Find lambda for endomorphism. Skip if none can be found.74lam = None75for l in cbrts:76if l*gen == E(BETA*gen[0], gen[1]):77lam = l78break80if lam is None:81no_endo_count += 182else:83sol_count += 184solutions.setdefault(f, []).append((b, int(gen[0]), int(gen[1]), gen, lam))86print(f" - Found {sol_count} generators (plus {no_endo_count} without endomorphism)")88print()90def output_generator(g, name):91print(f"#define {name} SECP256K1_GE_CONST(\\")92print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4)))93print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))94print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4)))95print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))96print(")")98def output_b(b):99print(f"#define SECP256K1_B {int(b)}")101print()102print("To be put in src/group_impl.h:")103print()104print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */")105for f in sorted(solutions.keys()):106# Use as generator/2 the one with lowest b, and lowest (x, y) generator (interpreted as non-negative integers).107b, _, _, HALF_G, lam = min(solutions[f])108output_generator(2 * HALF_G, f"SECP256K1_G_ORDER_{f}")109print("/** Generator for secp256k1, value 'g' defined in")110print(" * \"Standards for Efficient Cryptography\" (SEC2) 2.7.1.")111print(" */")112output_generator(G, "SECP256K1_G")113print("/* These exhaustive group test orders and generators are chosen such that:")114print(" * - The field size is equal to that of secp256k1, so field code is the same.")115print(" * - The curve equation is of the form y^2=x^3+B for some small constant B.")116print(" * - The subgroup has a generator 2*P, where P.x is as small as possible.")117print(f" * - The subgroup has size less than {MAX_ORDER} to permit exhaustive testing.")118print(" * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y).")119print(" */")120print("#if defined(EXHAUSTIVE_TEST_ORDER)")121first = True122for f in sorted(solutions.keys()):123b, _, _, _, lam = min(solutions[f])124print(f"# {'if' if first else 'elif'} EXHAUSTIVE_TEST_ORDER == {f}")125first = False126print()127print(f"static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_{f};")128output_b(b)129print()130print("# else")131print("# error No known generator for the specified exhaustive test group order.")132print("# endif")133print("#else")134print()135print("static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;")136output_b(7)137print()138print("#endif")139print("/* End of section generated by sage/gen_exhaustive_groups.sage. */")142print()143print()144print("To be put in src/scalar_impl.h:")145print()146print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */")147first = True148for f in sorted(solutions.keys()):149_, _, _, _, lam = min(solutions[f])150print("# %s EXHAUSTIVE_TEST_ORDER == %i" % ("if" if first else "elif", f))151first = False152print("# define EXHAUSTIVE_TEST_LAMBDA %i" % lam)153print("# else")154print("# error No known lambda for the specified exhaustive test group order.")155print("# endif")156print("/* End of section generated by sage/gen_exhaustive_groups.sage. */")
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.