Find index of an incorrect character in a Bech32 string. */
| 393 | |
| 394 | /** Find index of an incorrect character in a Bech32 string. */ |
| 395 | std::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; |