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

Function LocateErrors

src/bech32.cpp:395–562  ·  view source on GitHub ↗

Find index of an incorrect character in a Bech32 string. */

Source from the content-addressed store, hash-verified

393
394/** Find index of an incorrect character in a Bech32 string. */
395std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str) {
396 std::vector<int> error_locations{};
397
398 if (str.size() > 90) {
399 error_locations.resize(str.size() - 90);
400 std::iota(error_locations.begin(), error_locations.end(), 90);
401 return std::make_pair("Bech32 string too long", std::move(error_locations));
402 }
403
404 if (!CheckCharacters(str, error_locations)){
405 return std::make_pair("Invalid character or mixed case", std::move(error_locations));
406 }
407
408 size_t pos = str.rfind('1');
409 if (pos == str.npos) {
410 return std::make_pair("Missing separator", std::vector<int>{});
411 }
412 if (pos == 0 || pos + 7 > str.size()) {
413 error_locations.push_back(pos);
414 return std::make_pair("Invalid separator position", std::move(error_locations));
415 }
416
417 std::string hrp;
418 for (size_t i = 0; i < pos; ++i) {
419 hrp += LowerCase(str[i]);
420 }
421
422 size_t length = str.size() - 1 - pos; // length of data part
423 data values(length);
424 for (size_t i = pos + 1; i < str.size(); ++i) {
425 unsigned char c = str[i];
426 int8_t rev = CHARSET_REV[c];
427 if (rev == -1) {
428 error_locations.push_back(i);
429 return std::make_pair("Invalid Base 32 character", std::move(error_locations));
430 }
431 values[i - pos - 1] = rev;
432 }
433
434 // We attempt error detection with both bech32 and bech32m, and choose the one with the fewest errors
435 // We can't simply use the segwit version, because that may be one of the errors
436 std::optional<Encoding> error_encoding;
437 for (Encoding encoding : {Encoding::BECH32, Encoding::BECH32M}) {
438 std::vector<int> possible_errors;
439 // Recall that (ExpandHRP(hrp) ++ values) is interpreted as a list of coefficients of a polynomial
440 // over GF(32). PolyMod computes the "remainder" of this polynomial modulo the generator G(x).
441 uint32_t residue = PolyMod(Cat(ExpandHRP(hrp), values)) ^ EncodingConstant(encoding);
442
443 // All valid codewords should be multiples of G(x), so this remainder (after XORing with the encoding
444 // constant) should be 0 - hence 0 indicates there are no errors present.
445 if (residue != 0) {
446 // If errors are present, our polynomial must be of the form C(x) + E(x) where C is the valid
447 // codeword (a multiple of G(x)), and E encodes the errors.
448 uint32_t syn = Syndrome(residue);
449
450 // Unpack the three 10-bit syndrome values
451 int s0 = syn & 0x3FF;
452 int s1 = (syn >> 10) & 0x3FF;

Callers 2

DecodeDestinationFunction · 0.85
BOOST_AUTO_TEST_CASEFunction · 0.85

Calls 13

CheckCharactersFunction · 0.85
SyndromeFunction · 0.85
LowerCaseFunction · 0.70
PolyModFunction · 0.70
CatFunction · 0.70
ExpandHRPFunction · 0.70
EncodingConstantFunction · 0.70
sizeMethod · 0.45
resizeMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
push_backMethod · 0.45

Tested by 1

BOOST_AUTO_TEST_CASEFunction · 0.68