Repository: bitcoin/bitcoin
File: src/bech32.cpp (C++)

Code before:
    auto enc = PreparePolynomialCoefficients(hrp, values);
    enc.insert(enc.end(), CHECKSUM_SIZE, 0x00);
    uint32_t mod = PolyMod(enc) ^ EncodingConstant(encoding); // Determine what to XOR into those 6 zeroes.
    data ret(CHECKSUM_SIZE);
    for (size_t i = 0; i < CHECKSUM_SIZE; ++i) {
        // Convert the 5-bit groups in mod to checksum values.
        ret[i] = (mod >> (5 * (5 - i))) & 31;
    }
    return ret;
}

} // namespace

/** Encode a Bech32 or Bech32m string. */
std::string Encode(Encoding encoding, const std::string& hrp, const data& values) {
    // First ensure that the HRP is all lowercase. BIP-173 and BIP350 require an encoder
    // to return a lowercase Bech32/Bech32m string, but if given an uppercase HRP, the
    // result will always be invalid.
    for (const char& c : hrp) assert(c < 'A' || c > 'Z');
    data checksum = CreateChecksum(encoding, hrp, values);
    data combined = Cat(values, checksum);
    std::string ret = hrp + '1';
    ret.reserve(ret.size() + combined.size());
    for (const auto c : combined) {
        ret += CHARSET[c];
    }
    return ret;
}

/** Decode a Bech32 or Bech32m string. */
DecodeResult Decode(const std::string& str, CharLimit limit) {
    std::vector<int> errors;
    if (!CheckCharacters(str, errors)) return {};
    size_t pos = str.rfind('1');
    if (str.size() > limit) return {};
    if (pos == str.npos || pos == 0 || pos + CHECKSUM_SIZE >= str.size()) {
        return {};
    }
    data values(str.size() - 1 - pos);
    for (size_t i = 0; i < str.size() - 1 - pos; ++i) {
        unsigned char c = str[i + pos + 1];
        int8_t rev = CHARSET_REV[c];

        if (rev == -1) {
            return {};
        }
        values[i] = rev;
    }
    std::string hrp;
    for (size_t i = 0; i < pos; ++i) {
        hrp += LowerCase(str[i]);

Review comment (bug):
in https://github.com/bitcoin/bitcoin/pull/29607/commits/e7c55d4f4dea4c42b40ff326a17e6884de181ed6:

Is there a reason to prefer `auto` over explicitly mentioning the types? I find it to be more readable as 

```suggestion
    for (const char& c : hrp) assert(c < 'A' || c > 'Z');

    std::string ret;
    ret.reserve(hrp.size() + 1 + values.size() + CHECKSUM_SIZE);
    ret += hrp;
    ret += '1';
    for (const uint8_t& i : values) ret += CHARSET[i];
    for (const uint8_t& i : CreateChecksum(encoding, hrp, values)) ret += CHARSET[i];
```

since in the second and third loop its not actually a character, but an index for the character in the `CHARSET`array. Using `auto c` leaves the impression that its all characters, which is incorrect.

Code after:
    auto enc = PreparePolynomialCoefficients(hrp, values);
    enc.insert(enc.end(), CHECKSUM_SIZE, 0x00);
    uint32_t mod = PolyMod(enc) ^ EncodingConstant(encoding); // Determine what to XOR into those 6 zeroes.
    data ret(CHECKSUM_SIZE);
    for (size_t i = 0; i < CHECKSUM_SIZE; ++i) {
        // Convert the 5-bit groups in mod to checksum values.
        ret[i] = (mod >> (5 * (5 - i))) & 31;
    }
    return ret;
}

} // namespace

/** Encode a Bech32 or Bech32m string. */
std::string Encode(Encoding encoding, const std::string& hrp, const data& values) {
    // First ensure that the HRP is all lowercase. BIP-173 and BIP350 require an encoder
    // to return a lowercase Bech32/Bech32m string, but if given an uppercase HRP, the
    // result will always be invalid.
    for (const char& c : hrp) assert(c < 'A' || c > 'Z');

    std::string ret;
    ret.reserve(hrp.size() + 1 + values.size() + CHECKSUM_SIZE);
    ret += hrp;
    ret += '1';
    for (const uint8_t& i : values) ret += CHARSET[i];
    for (const uint8_t& i : CreateChecksum(encoding, hrp, values)) ret += CHARSET[i];
    return ret;
}

/** Decode a Bech32 or Bech32m string. */
DecodeResult Decode(const std::string& str, CharLimit limit) {
    std::vector<int> errors;
    if (!CheckCharacters(str, errors)) return {};
    size_t pos = str.rfind('1');
    if (str.size() > limit) return {};
    if (pos == str.npos || pos == 0 || pos + CHECKSUM_SIZE >= str.size()) {
        return {};
    }
    data values(str.size() - 1 - pos);
    for (size_t i = 0; i < str.size() - 1 - pos; ++i) {
        unsigned char c = str[i + pos + 1];
        int8_t rev = CHARSET_REV[c];

        if (rev == -1) {
            return {};
        }
        values[i] = rev;
    }
    std::string hrp;
    hrp.reserve(pos);
    for (size_t i = 0; i < pos; ++i) {