MCPcopy Create free account
hub / github.com/ElementsProject/elements / PolyMod

Function PolyMod

src/bech32.cpp:127–213  ·  view source on GitHub ↗

This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to * make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher * bits correspond to earlier values. */

Source from the content-addressed store, hash-verified

125 * make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher
126 * bits correspond to earlier values. */
127uint32_t PolyMod(const data& v)
128{
129 // The input is interpreted as a list of coefficients of a polynomial over F = GF(32), with an
130 // implicit 1 in front. If the input is [v0,v1,v2,v3,v4], that polynomial is v(x) =
131 // 1*x^5 + v0*x^4 + v1*x^3 + v2*x^2 + v3*x + v4. The implicit 1 guarantees that
132 // [v0,v1,v2,...] has a distinct checksum from [0,v0,v1,v2,...].
133
134 // The output is a 30-bit integer whose 5-bit groups are the coefficients of the remainder of
135 // v(x) mod g(x), where g(x) is the Bech32 generator,
136 // x^6 + {29}x^5 + {22}x^4 + {20}x^3 + {21}x^2 + {29}x + {18}. g(x) is chosen in such a way
137 // that the resulting code is a BCH code, guaranteeing detection of up to 3 errors within a
138 // window of 1023 characters. Among the various possible BCH codes, one was selected to in
139 // fact guarantee detection of up to 4 errors within a window of 89 characters.
140
141 // Note that the coefficients are elements of GF(32), here represented as decimal numbers
142 // between {}. In this finite field, addition is just XOR of the corresponding numbers. For
143 // example, {27} + {13} = {27 ^ 13} = {22}. Multiplication is more complicated, and requires
144 // treating the bits of values themselves as coefficients of a polynomial over a smaller field,
145 // GF(2), and multiplying those polynomials mod a^5 + a^3 + 1. For example, {5} * {26} =
146 // (a^2 + 1) * (a^4 + a^3 + a) = (a^4 + a^3 + a) * a^2 + (a^4 + a^3 + a) = a^6 + a^5 + a^4 + a
147 // = a^3 + 1 (mod a^5 + a^3 + 1) = {9}.
148
149 // During the course of the loop below, `c` contains the bitpacked coefficients of the
150 // polynomial constructed from just the values of v that were processed so far, mod g(x). In
151 // the above example, `c` initially corresponds to 1 mod g(x), and after processing 2 inputs of
152 // v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
153 // for `c`.
154
155 // The following Sage code constructs the generator used:
156 //
157 // B = GF(2) # Binary field
158 // BP.<b> = B[] # Polynomials over the binary field
159 // F_mod = b**5 + b**3 + 1
160 // F.<f> = GF(32, modulus=F_mod, repr='int') # GF(32) definition
161 // FP.<x> = F[] # Polynomials over GF(32)
162 // E_mod = x**2 + F.fetch_int(9)*x + F.fetch_int(23)
163 // E.<e> = F.extension(E_mod) # GF(1024) extension field definition
164 // for p in divisors(E.order() - 1): # Verify e has order 1023.
165 // assert((e**p == 1) == (p % 1023 == 0))
166 // G = lcm([(e**i).minpoly() for i in range(997,1000)])
167 // print(G) # Print out the generator
168 //
169 // It demonstrates that g(x) is the least common multiple of the minimal polynomials
170 // of 3 consecutive powers (997,998,999) of a primitive element (e) of GF(1024).
171 // That guarantees it is, in fact, the generator of a primitive BCH code with cycle
172 // length 1023 and distance 4. See https://en.wikipedia.org/wiki/BCH_code for more details.
173
174 uint32_t c = 1;
175 for (const auto v_i : v) {
176 // We want to update `c` to correspond to a polynomial with one extra term. If the initial
177 // value of `c` consists of the coefficients of c(x) = f(x) mod g(x), we modify it to
178 // correspond to c'(x) = (f(x) * x + v_i) mod g(x), where v_i is the next input to
179 // process. Simplifying:
180 // c'(x) = (f(x) * x + v_i) mod g(x)
181 // ((f(x) mod g(x)) * x + v_i) mod g(x)
182 // (c(x) * x + v_i) mod g(x)
183 // If c(x) = c0*x^5 + c1*x^4 + c2*x^3 + c3*x^2 + c4*x + c5, we want to compute
184 // c'(x) = (c0*x^5 + c1*x^4 + c2*x^3 + c3*x^2 + c4*x + c5) * x + v_i mod g(x)

Callers 3

VerifyChecksumFunction · 0.70
CreateChecksumFunction · 0.70
LocateErrorsFunction · 0.70

Calls

no outgoing calls

Tested by

no test coverage detected