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.
501*η=-δ*. In this representation, negating *δ* corresponds to negating *η*, and incrementing502*δ* corresponds to decrementing *η*. This allows us to remove the negation in the *c1*503computation:505```python506# Compute a mask c1 for eta < 0, and compute the conditional negation x of f:507c1 = eta >> 63508x = (f ^ c1) - c1509# Compute a mask c2 for odd g, and conditionally add x to g:510c2 = -(g & 1)511g += x & c2512# Compute a mask c for (eta < 0) and odd (input) g, and use it to conditionally negate eta,513# and add g to f:514c3 = c1 & c2515eta = (eta ^ c3) - c3516f += g & c3517# Incrementing delta corresponds to decrementing eta.518eta -= 1519g >>= 1520```522A variant of divsteps with better worst-case performance can be used instead: starting *δ* at523*1/2* instead of *1*. This reduces the worst case number of iterations to *590* for *256*-bit inputs524(which can be shown using convex hull analysis). In this case, the substitution *ζ=-(δ+1/2)*525is used instead to keep the variable integral. Incrementing *δ* by *1* still translates to526decrementing *ζ* by *1*, but negating *δ* now corresponds to going from *ζ* to *-(ζ+1)*, or527*~ζ*. Doing that conditionally based on *c3* is simply:529```python530...531c3 = c1 & c2532zeta ^= c3533...534```536By replacing the loop in `divsteps_n_matrix` with a variant of the divstep code above (extended to537also apply all *f* operations to *u*, *v* and all *g* operations to *q*, *r*), a constant-time version of538`divsteps_n_matrix` is obtained. The full code will be in section 7.540These bit fiddling tricks can also be used to make the conditional negations and additions in541`update_de` and `normalize` constant-time.544## 6. Variable-time optimizations546In section 5, we modified the `divsteps_n_matrix` function (and a few others) to be constant time.547Constant time operations are only necessary when computing modular inverses of secret data. In548other cases, it slows down calculations unnecessarily. In this section, we will construct a549faster non-constant time `divsteps_n_matrix` function.551To do so, first consider yet another way of writing the inner loop of divstep operations in552`gcd` from section 1. This decomposition is also explained in the paper in section 8.2. We use553the original version with initial *δ=1* and *η=-δ* here.555```python556for _ in range(N):557if g & 1 and eta < 0:558eta, f, g = -eta, g, -f559if g & 1:560g += f561eta -= 1562g >>= 1563```565Whenever *g* is even, the loop only shifts *g* down and decreases *η*. When *g* ends in multiple zero566bits, these iterations can be consolidated into one step. This requires counting the bottom zero567bits efficiently, which is possible on most platforms; it is abstracted here as the function568`count_trailing_zeros`.570```python571def count_trailing_zeros(v):572"""573When v is zero, consider all N zero bits as "trailing".574For a non-zero value v, find z such that v=(d<<z) for some odd d.575"""576if v == 0:577return N578else:579return (v & -v).bit_length() - 1581i = N # divsteps left to do582while True:583# Get rid of all bottom zeros at once. In the first iteration, g may be odd and the following584# lines have no effect (until "if eta < 0").585zeros = min(i, count_trailing_zeros(g))586eta -= zeros587g >>= zeros588i -= zeros589if i == 0:590break591# We know g is odd now592if eta < 0:593eta, f, g = -eta, g, -f594g += f595# g is even now, and the eta decrement and g shift will happen in the next loop.596```598We can now remove multiple bottom *0* bits from *g* at once, but still need a full iteration whenever599there is a bottom *1* bit. In what follows, we will get rid of multiple *1* bits simultaneously as600well.602Observe that as long as *η ≥ 0*, the loop does not modify *f*. Instead, it cancels out bottom603bits of *g* and shifts them out, and decreases *η* and *i* accordingly - interrupting only when *η*604becomes negative, or when *i* reaches *0*. Combined, this is equivalent to adding a multiple of *f* to605*g* to cancel out multiple bottom bits, and then shifting them out.607It is easy to find what that multiple is: we want a number *w* such that *g+w f* has a few bottom608zero bits. If that number of bits is *L*, we want *g+w f mod 2<sup>L</sup> = 0*, or *w = -g/f mod 2<sup>L</sup>*. Since *f*609is odd, such a *w* exists for any *L*. *L* cannot be more than *i* steps (as we'd finish the loop before610doing more) or more than *η+1* steps (as we'd run `eta, f, g = -eta, g, -f` at that point), but611apart from that, we're only limited by the complexity of computing *w*.613This code demonstrates how to cancel up to 4 bits per step:615```python616NEGINV16 = [15, 5, 3, 9, 7, 13, 11, 1] # NEGINV16[n//2] = (-n)^-1 mod 16, for odd n617i = N618while True:619zeros = min(i, count_trailing_zeros(g))620eta -= zeros621g >>= zeros622i -= zeros623if i == 0:624break625# We know g is odd now626if eta < 0:627eta, f, g = -eta, g, -f628# Compute limit on number of bits to cancel629limit = min(min(eta + 1, i), 4)630# Compute w = -g/f mod 2**limit, using the table value for -1/f mod 2**4. Note that f is631# always odd, so its inverse modulo a power of two always exists.632w = (g * NEGINV16[(f & 15) // 2]) % (2**limit)633# As w = -g/f mod (2**limit), g+w*f mod 2**limit = 0 mod 2**limit.634g += w * f635assert g % (2**limit) == 0636# The next iteration will now shift out at least limit bottom zero bits from g.637```639By using a bigger table more bits can be cancelled at once. The table can also be implemented640as a formula. Several formulas are known for computing modular inverses modulo powers of two;641some can be found in Hacker's Delight second edition by Henry S. Warren, Jr. pages 245-247.642Here we need the negated modular inverse, which is a simple transformation of those:644- Instead of a 3-bit table:645- *-f* or *f ^ 6*646- Instead of a 4-bit table:647- *1 - f(f + 1)*648- *-(f + (((f + 1) & 4) << 1))*649- For larger tables the following technique can be used: if *w=-1/f mod 2<sup>L</sup>*, then *w(w f+2)* is650*-1/f mod 2<sup>2L</sup>*. This allows extending the previous formulas (or tables). In particular we651have this 6-bit function (based on the 3-bit function above):652- *f(f<sup>2</sup> - 2)*654This loop, again extended to also handle *u*, *v*, *q*, and *r* alongside *f* and *g*, placed in655`divsteps_n_matrix`, gives a significantly faster, but non-constant time version.658## 7. Final Python version660All together we need the following functions:662- A way to compute the transition matrix in constant time, using the `divsteps_n_matrix` function663from section 2, but with its loop replaced by a variant of the constant-time divstep from664section 5, extended to handle *u*, *v*, *q*, *r*:666```python667def divsteps_n_matrix(zeta, f, g):668"""Compute zeta and transition matrix t after N divsteps (multiplied by 2^N)."""669u, v, q, r = 1, 0, 0, 1 # start with identity matrix670for _ in range(N):671c1 = zeta >> 63672# Compute x, y, z as conditionally-negated versions of f, u, v.673x, y, z = (f ^ c1) - c1, (u ^ c1) - c1, (v ^ c1) - c1674c2 = -(g & 1)675# Conditionally add x, y, z to g, q, r.676g, q, r = g + (x & c2), q + (y & c2), r + (z & c2)677c1 &= c2 # reusing c1 here for the earlier c3 variable678zeta = (zeta ^ c1) - 1 # inlining the unconditional zeta decrement here679# Conditionally add g, q, r to f, u, v.680f, u, v = f + (g & c1), u + (q & c1), v + (r & c1)681# When shifting g down, don't shift q, r, as we construct a transition matrix multiplied682# by 2^N. Instead, shift f's coefficients u and v up.683g, u, v = g >> 1, u << 1, v << 1684return zeta, (u, v, q, r)685```687- The functions to update *f* and *g*, and *d* and *e*, from section 2 and section 4, with the constant-time688changes to `update_de` from section 5:690```python691def update_fg(f, g, t):692"""Multiply matrix t/2^N with [f, g]."""693u, v, q, r = t694cf, cg = u*f + v*g, q*f + r*g695return cf >> N, cg >> N697def update_de(d, e, t, M, Mi):698"""Multiply matrix t/2^N with [d, e], modulo M."""699u, v, q, r = t700d_sign, e_sign = d >> 257, e >> 257701md, me = (u & d_sign) + (v & e_sign), (q & d_sign) + (r & e_sign)702cd, ce = (u*d + v*e) % 2**N, (q*d + r*e) % 2**N703md -= (Mi*cd + md) % 2**N704me -= (Mi*ce + me) % 2**N705cd, ce = u*d + v*e + M*md, q*d + r*e + M*me706return cd >> N, ce >> N707```709- The `normalize` function from section 4, made constant time as well:711```python712def normalize(sign, v, M):713"""Compute sign*v mod M, where v in (-2*M,M); output in [0,M)."""714v_sign = v >> 257715# Conditionally add M to v.716v += M & v_sign717c = (sign - 1) >> 1718# Conditionally negate v.719v = (v ^ c) - c720v_sign = v >> 257721# Conditionally add M to v again.722v += M & v_sign723return v724```726- And finally the `modinv` function too, adapted to use *ζ* instead of *δ*, and using the fixed727iteration count from section 5:729```python730def modinv(M, Mi, x):731"""Compute the modular inverse of x mod M, given Mi=1/M mod 2^N."""732zeta, f, g, d, e = -1, M, x, 0, 1733for _ in range((590 + N - 1) // N):734zeta, t = divsteps_n_matrix(zeta, f % 2**N, g % 2**N)735f, g = update_fg(f, g, t)736d, e = update_de(d, e, t, M, Mi)737return normalize(f, d, M)738```740- To get a variable time version, replace the `divsteps_n_matrix` function with one that uses the741divsteps loop from section 5, and a `modinv` version that calls it without the fixed iteration742count:744```python745NEGINV16 = [15, 5, 3, 9, 7, 13, 11, 1] # NEGINV16[n//2] = (-n)^-1 mod 16, for odd n746def divsteps_n_matrix_var(eta, f, g):747"""Compute eta and transition matrix t after N divsteps (multiplied by 2^N)."""748u, v, q, r = 1, 0, 0, 1749i = N750while True:
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.