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#!/usr/bin/env sage2r"""3Generate finite field parameters for minisketch.5This script selects the finite fields used by minisketch6for various sizes and generates the required tables for7the implementation.9The output (after formatting) can be found in src/fields/*.cpp.11"""12B.<b> = GF(2)13P.<p> = B[]15def apply_map(m, v):16r = 017i = 018while v != 0:19if (v & 1):20r ^^= m[i]21i += 122v >>= 123return r25def recurse_moduli(acc, maxweight, maxdegree):26for pos in range(maxweight, maxdegree + 1, 1):27poly = acc + p^pos28if maxweight == 1:29if poly.is_irreducible():30return (pos, poly)31else:32(deg, ret) = recurse_moduli(poly, maxweight - 1, pos - 1)33if ret is not None:34return (pos, ret)35return (None, None)37def compute_moduli(bits):38# Return all optimal irreducible polynomials for GF(2^bits)39# The result is a list of tuples (weight, degree of second-highest nonzero coefficient, polynomial)40maxdegree = bits - 141result = []42for weight in range(1, bits, 2):43deg, res = None, None44while True:45ret = recurse_moduli(p^bits + 1, weight, maxdegree)46if ret[0] is not None:47(deg, res) = ret48maxdegree = deg - 149else:50break51if res is not None:52result.append((weight + 2, deg, res))53return result55def bits_to_int(vals):56ret = 057base = 158for val in vals:59ret += Integer(val) * base60base *= 261return ret63def sqr_table(f, bits, n=1):64ret = []65for i in range(bits):66ret.append((f^(2^n*i)).integer_representation())67return ret69# Compute x**(2**n)70def pow2(x, n):71for i in range(n):72x = x**273return x75def qrt_table(F, f, bits):76# Table for solving x2 + x = a77# This implements the technique from https://www.raco.cat/index.php/PublicacionsMatematiques/article/viewFile/37927/40412, Lemma 178for i in range(bits):79if (f**i).trace() != 0:80u = f**i81ret = []82for i in range(0, bits):83d = f^i84y = sum(pow2(d, j) * sum(pow2(u, k) for k in range(j)) for j in range(1, bits))85ret.append(y.integer_representation() ^^ (y.integer_representation() & 1))86return ret88def conv_tables(F, NF, bits):89# Generate a F(2) linear projection that maps elements from one field90# to an isomorphic field with a different modulus.91f = F.gen()92fp = f.minimal_polynomial()93assert(fp == F.modulus())94nfp = fp.change_ring(NF)95nf = sorted(nfp.roots(multiplicities=False))[0]96ret = []97matrepr = [[B(0) for x in range(bits)] for y in range(bits)]98for i in range(bits):99val = (nf**i).integer_representation()100ret.append(val)101for j in range(bits):102matrepr[j][i] = B((val >> j) & 1)103mat = Matrix(matrepr).inverse().transpose()104ret2 = []105for i in range(bits):106ret2.append(bits_to_int(mat[i]))108for t in range(100):109f1a = F.random_element()110f1b = F.random_element()111f1r = f1a * f1b112f2a = NF.fetch_int(apply_map(ret, f1a.integer_representation()))113f2b = NF.fetch_int(apply_map(ret, f1b.integer_representation()))114f2r = NF.fetch_int(apply_map(ret, f1r.integer_representation()))115f2s = f2a * f2b116assert(f2r == f2s)118for t in range(100):119f2a = NF.random_element()120f2b = NF.random_element()121f2r = f2a * f2b122f1a = F.fetch_int(apply_map(ret2, f2a.integer_representation()))123f1b = F.fetch_int(apply_map(ret2, f2b.integer_representation()))124f1r = F.fetch_int(apply_map(ret2, f2r.integer_representation()))125f1s = f1a * f1b126assert(f1r == f1s)128return (ret, ret2)130def fmt(i,typ):131if i == 0:132return "0"133else:134return "0x%x" % i136def lintranstype(typ, bits, maxtbl):137gsize = min(maxtbl, bits)138array_size = (bits + gsize - 1) // gsize139bits_list = []140total = 0141for i in range(array_size):142rsize = (bits - total + array_size - i - 1) // (array_size - i)143total += rsize144bits_list.append(rsize)145return "RecLinTrans<%s, %s>" % (typ, ", ".join("%i" % x for x in bits_list))147INT=0148CLMUL=1149CLMUL_TRI=2150MD=3152def print_modulus_md(mod):153ret = ""154pos = mod.degree()155for c in reversed(list(mod)):156if c:157if ret:158ret += " + "159if pos == 0:160ret += "1"161elif pos == 1:162ret += "x"163else:164ret += "x<sup>%i</sup>" % pos165pos -= 1166return ret168def pick_modulus(bits, style):169# Choose the lexicographicly-first lowest-weight modulus170# optionally subject to implementation specific constraints.171moduli = compute_moduli(bits)172if style == INT or style == MD:173multi_sqr = False174need_trans = False175elif style == CLMUL:176# Fast CLMUL reduction requires that bits + the highest177# set bit are less than 66.178moduli = list(filter((lambda x: bits+x[1] <= 66), moduli)) + moduli179multi_sqr = True180need_trans = True181if not moduli or moduli[0][2].change_ring(ZZ)(2) == 3 + 2**bits:182# For modulus 3, CLMUL_TRI is obviously better.183return None184elif style == CLMUL_TRI:185moduli = list(filter(lambda x: bits+x[1] <= 66, moduli)) + moduli186moduli = list(filter(lambda x: x[0] == 3, moduli))187multi_sqr = True188need_trans = True189else:190assert(False)191if not moduli:192return None193return moduli[0][2]195def print_result(bits, style):196if style == INT:197multi_sqr = False198need_trans = False199table_id = "%i" % bits200elif style == MD:201pass202elif style == CLMUL:203multi_sqr = True204need_trans = True205table_id = "%i" % bits206elif style == CLMUL_TRI:207multi_sqr = True208need_trans = True209table_id = "TRI%i" % bits210else:211assert(False)213nmodulus = pick_modulus(bits, INT)214modulus = pick_modulus(bits, style)215if modulus is None:216return218if style == MD:219print("* *%s*" % print_modulus_md(modulus))220return222if bits > 32:223typ = "uint64_t"224elif bits > 16:225typ = "uint32_t"226elif bits > 8:227typ = "uint16_t"228else:229typ = "uint8_t"231ttyp = lintranstype(typ, bits, 4)232rtyp = lintranstype(typ, bits, 6)234F.<f> = GF(2**bits, modulus=modulus)236include_table = True237if style != INT and style != CLMUL:238cmodulus = pick_modulus(bits, CLMUL)239if cmodulus == modulus:240include_table = False241table_id = "%i" % bits243if include_table:244print("typedef %s StatTable%s;" % (rtyp, table_id))245rtyp = "StatTable%s" % table_id246if (style == INT):247print("typedef %s DynTable%s;" % (ttyp, table_id))248ttyp = "DynTable%s" % table_id250if need_trans:
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.