16typedef std::vector<uint8_t> data;
19const char* CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
22const int8_t CHARSET_REV[128] = {
23 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
24 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
25 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
26 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
27 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
28 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
29 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
30 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
34uint32_t EncodingConstant(
Encoding encoding) {
42uint32_t PolyMod(
const data& v)
90 for (
const auto v_i : v) {
106 uint8_t c0 = c >> 25;
109 c = ((c & 0x1ffffff) << 5) ^ v_i;
120 if (c0 & 1) c ^= 0x3b6a57b2;
121 if (c0 & 2) c ^= 0x26508e6d;
122 if (c0 & 4) c ^= 0x1ea119fa;
123 if (c0 & 8) c ^= 0x3d4233dd;
124 if (c0 & 16) c ^= 0x2a1462b3;
131inline unsigned char LowerCase(
unsigned char c)
133 return (c >=
'A' && c <=
'Z') ? (c -
'A') +
'a' : c;
137data ExpandHRP(
const std::string& hrp)
140 ret.reserve(hrp.size() + 90);
141 ret.resize(hrp.size() * 2 + 1);
142 for (
size_t i = 0; i < hrp.size(); ++i) {
143 unsigned char c = hrp[i];
145 ret[i + hrp.size() + 1] = c & 0x1f;
152Encoding VerifyChecksum(
const std::string& hrp,
const data&
values)
159 const uint32_t check = PolyMod(
Cat(ExpandHRP(hrp),
values));
166data CreateChecksum(
Encoding encoding,
const std::string& hrp,
const data&
values)
169 enc.resize(enc.size() + 6);
170 uint32_t mod = PolyMod(enc) ^ EncodingConstant(encoding);
172 for (
size_t i = 0; i < 6; ++i) {
174 ret[i] = (mod >> (5 * (5 - i))) & 31;
186 for (
const char& c : hrp)
assert(c < 'A' || c >
'Z');
187 data checksum = CreateChecksum(encoding, hrp,
values);
189 std::string ret = hrp +
'1';
190 ret.reserve(ret.size() + combined.size());
191 for (
const auto c : combined) {
199 bool lower =
false, upper =
false;
200 for (
size_t i = 0; i < str.size(); ++i) {
201 unsigned char c = str[i];
202 if (c >=
'a' && c <=
'z') lower =
true;
203 else if (c >=
'A' && c <=
'Z') upper =
true;
204 else if (c < 33 || c > 126)
return {};
206 if (lower && upper)
return {};
207 size_t pos = str.rfind(
'1');
208 if (str.size() > 90 || pos == str.npos || pos == 0 || pos + 7 > str.size()) {
211 data
values(str.size() - 1 - pos);
212 for (
size_t i = 0; i < str.size() - 1 - pos; ++i) {
213 unsigned char c = str[i + pos + 1];
214 int8_t rev = CHARSET_REV[c];
222 for (
size_t i = 0; i < pos; ++i) {
223 hrp += LowerCase(str[i]);
227 return {result, std::move(hrp), data(
values.begin(),
values.end() - 6)};
@ INVALID
Failed decoding.
@ BECH32
Bech32 encoding as defined in BIP173.
@ BECH32M
Bech32m encoding as defined in BIP350.
std::string Encode(Encoding encoding, const std::string &hrp, const data &values)
Encode a Bech32 or Bech32m string.
DecodeResult Decode(const std::string &str)
Decode a Bech32 or Bech32m string.
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
V Cat(V v1, V &&v2)
Concatenate two vectors, moving elements.