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.
501int s2_s1p1 = s2 ^ (s1 == 0 ? 0 : GF1024_EXP.at((l_s1 + p1) % 1023));502if (s2_s1p1 == 0) continue;503int l_s2_s1p1 = GF1024_LOG.at(s2_s1p1);505// Similarly, s1 + s0*(e)^p1506// = e2*(e)^(997*p2) ((e)^p2 + (e)^p1)507int s1_s0p1 = s1 ^ (s0 == 0 ? 0 : GF1024_EXP.at((l_s0 + p1) % 1023));508if (s1_s0p1 == 0) continue;509int l_s1_s0p1 = GF1024_LOG.at(s1_s0p1);511// So, putting these together, we can compute the second error position as512// (e)^p2 = (s2 + s1^p1)/(s1 + s0^p1)513// p2 = log((e)^p2)514size_t p2 = (l_s2_s1p1 - l_s1_s0p1 + 1023) % 1023;516// Sanity checks that p2 is a valid position and not the same as p1517if (p2 >= length || p1 == p2) continue;519// Now we want to compute the error values e1 and e2.520// Similar to above, we compute s1 + s0*(e)^p2521// = e1*(e)^(997*p1) ((e)^p1 + (e)^p2)522int s1_s0p2 = s1 ^ (s0 == 0 ? 0 : GF1024_EXP.at((l_s0 + p2) % 1023));523if (s1_s0p2 == 0) continue;524int l_s1_s0p2 = GF1024_LOG.at(s1_s0p2);526// And compute (the log of) 1/((e)^p1 + (e)^p2))527int inv_p1_p2 = 1023 - GF1024_LOG.at(GF1024_EXP.at(p1) ^ GF1024_EXP.at(p2));529// Then (s1 + s0*(e)^p1) * (1/((e)^p1 + (e)^p2)))530// = e2*(e)^(997*p2)531// Then recover e2 by dividing by (e)^(997*p2)532int l_e2 = l_s1_s0p1 + inv_p1_p2 + (1023 - 997) * p2;533// Check that e2 is in GF(32)534if (l_e2 % 33) continue;536// In the same way, (s1 + s0*(e)^p2) * (1/((e)^p1 + (e)^p2)))537// = e1*(e)^(997*p1)538// So recover e1 by dividing by (e)^(997*p1)539int l_e1 = l_s1_s0p2 + inv_p1_p2 + (1023 - 997) * p1;540// Check that e1 is in GF(32)541if (l_e1 % 33) continue;543// Again, we do not return e1 or e2 for safety.544// Order the error positions from the left of the string and return them545if (p1 > p2) {546possible_errors.push_back(str.size() - p1 - 1);547possible_errors.push_back(str.size() - p2 - 1);548} else {549possible_errors.push_back(str.size() - p2 - 1);550possible_errors.push_back(str.size() - p1 - 1);551}552break;553}554}555} else {556// No errors557return std::make_pair("", std::vector<int>{});558}560if (error_locations.empty() || (!possible_errors.empty() && possible_errors.size() < error_locations.size())) {561error_locations = std::move(possible_errors);562if (!error_locations.empty()) error_encoding = encoding;563}564}565std::string error_message = error_encoding == Encoding::BECH32M ? "Invalid Bech32m checksum"566: error_encoding == Encoding::BECH32 ? "Invalid Bech32 checksum"567: "Invalid checksum";569return std::make_pair(error_message, std::move(error_locations));570}572} // namespace bech32