Skip to content

Commit 5676aec

Browse files
committed
refactor: Model the bech32 charlimit as an Enum
Bech32(m) was defined with a 90 character limit so that certain guarantees for error detection could be made for segwit addresses. However, there is nothing about the encoding scheme itself that requires a limit and in practice bech32(m) has been used without the 90 char limit (e.g. lightning invoices). Further, increasing the character limit doesn't do away with error detection, it simply lessons the guarantees. Model charlimit as an Enum, so that if a different address scheme is using bech32(m), the character limit for that address scheme can be used, rather than always using the 90 charlimit defined for segwit addresses. upate comment
1 parent 2cedb42 commit 5676aec

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

src/bech32.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,12 @@ std::string Encode(Encoding encoding, const std::string& hrp, const data& values
370370
}
371371

372372
/** Decode a Bech32 or Bech32m string. */
373-
DecodeResult Decode(const std::string& str) {
373+
DecodeResult Decode(const std::string& str, CharLimit limit) {
374374
std::vector<int> errors;
375375
if (!CheckCharacters(str, errors)) return {};
376376
size_t pos = str.rfind('1');
377-
if (str.size() > 90 || pos == str.npos || pos == 0 || pos + 7 > str.size()) {
377+
if (str.size() > limit) return {};
378+
if (pos == str.npos || pos == 0 || pos + 7 > str.size()) {
378379
return {};
379380
}
380381
data values(str.size() - 1 - pos);
@@ -397,12 +398,12 @@ DecodeResult Decode(const std::string& str) {
397398
}
398399

399400
/** Find index of an incorrect character in a Bech32 string. */
400-
std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str) {
401+
std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str, CharLimit limit) {
401402
std::vector<int> error_locations{};
402403

403-
if (str.size() > 90) {
404-
error_locations.resize(str.size() - 90);
405-
std::iota(error_locations.begin(), error_locations.end(), 90);
404+
if (str.size() > limit) {
405+
error_locations.resize(str.size() - limit);
406+
std::iota(error_locations.begin(), error_locations.end(), static_cast<int>(limit));
406407
return std::make_pair("Bech32 string too long", std::move(error_locations));
407408
}
408409

src/bech32.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ enum class Encoding {
2828
BECH32M, //!< Bech32m encoding as defined in BIP350
2929
};
3030

31+
/** Character limits for Bech32(m) encoded strings. Character limits are how we provide error location guarantees.
32+
* These values should never exceed 2^31 - 1 (max value for a 32-bit int), since there are places where we may need to
33+
* convert the CharLimit::VALUE to an int. In practice, this should never happen since this CharLimit applies to an address encoding
34+
* and we would never encode an address with such a massive value */
35+
enum CharLimit : size_t {
36+
BECH32 = 90, //!< BIP173/350 imposed character limit for Bech32(m) encoded addresses. This guarantees finding up to 4 errors.
37+
};
38+
3139
/** Encode a Bech32 or Bech32m string. If hrp contains uppercase characters, this will cause an
3240
* assertion error. Encoding must be one of BECH32 or BECH32M. */
3341
std::string Encode(Encoding encoding, const std::string& hrp, const std::vector<uint8_t>& values);
@@ -43,10 +51,10 @@ struct DecodeResult
4351
};
4452

4553
/** Decode a Bech32 or Bech32m string. */
46-
DecodeResult Decode(const std::string& str);
54+
DecodeResult Decode(const std::string& str, CharLimit limit = CharLimit::BECH32);
4755

4856
/** Return the positions of errors in a Bech32 string. */
49-
std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str);
57+
std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str, CharLimit limit = CharLimit::BECH32);
5058

5159
} // namespace bech32
5260

0 commit comments

Comments
 (0)