10 typedef std::vector<uint8_t> data;
13 const char* CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
16 const int8_t CHARSET_REV[128] = {
17 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
18 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
19 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
20 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
21 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
22 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
23 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
24 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
28 data Cat(data x,
const data& y)
30 x.insert(x.end(), y.begin(), y.end());
37 uint32_t PolyMod(
const data& v)
65 for (
const auto v_i : v) {
84 c = ((c & 0x1ffffff) << 5) ^ v_i;
87 if (c0 & 1) c ^= 0x3b6a57b2;
88 if (c0 & 2) c ^= 0x26508e6d;
89 if (c0 & 4) c ^= 0x1ea119fa;
90 if (c0 & 8) c ^= 0x3d4233dd;
91 if (c0 & 16) c ^= 0x2a1462b3;
97 inline unsigned char LowerCase(
unsigned char c)
99 return (c >=
'A' && c <=
'Z') ? (c -
'A') +
'a' : c;
103 data ExpandHRP(
const std::string& hrp)
106 ret.reserve(hrp.size() + 90);
107 ret.resize(hrp.size() * 2 + 1);
108 for (
size_t i = 0; i < hrp.size(); ++i) {
109 unsigned char c = hrp[i];
111 ret[i + hrp.size() + 1] = c & 0x1f;
118 bool VerifyChecksum(
const std::string& hrp,
const data& values)
124 return PolyMod(Cat(ExpandHRP(hrp), values)) == 1;
128 data CreateChecksum(
const std::string& hrp,
const data& values)
130 data enc = Cat(ExpandHRP(hrp), values);
131 enc.resize(enc.size() + 6);
132 uint32_t mod = PolyMod(enc) ^ 1;
134 for (
size_t i = 0; i < 6; ++i) {
136 ret[i] = (mod >> (5 * (5 - i))) & 31;
147 std::string
Encode(
const std::string& hrp,
const data& values) {
148 data checksum = CreateChecksum(hrp, values);
149 data combined = Cat(values, checksum);
150 std::string
ret = hrp +
'1';
152 for (
const auto c : combined) {
159 std::pair<std::string, data>
Decode(
const std::string& str) {
160 bool lower =
false, upper =
false;
161 for (
size_t i = 0; i < str.size(); ++i) {
162 unsigned char c = str[i];
163 if (c >=
'a' && c <=
'z') lower =
true;
164 else if (c >=
'A' && c <=
'Z') upper =
true;
165 else if (c < 33 || c > 126)
return {};
167 if (lower && upper)
return {};
168 size_t pos = str.rfind(
'1');
169 if (str.size() > 90 || pos == str.npos || pos == 0 || pos + 7 > str.size()) {
172 data values(str.size() - 1 - pos);
173 for (
size_t i = 0; i < str.size() - 1 - pos; ++i) {
174 unsigned char c = str[i + pos + 1];
175 int8_t rev = CHARSET_REV[c];
183 for (
size_t i = 0; i < pos; ++i) {
184 hrp += LowerCase(str[i]);
186 if (!VerifyChecksum(hrp, values)) {
189 return {hrp, data(values.begin(), values.end() - 6)};
UniValue ret(UniValue::VARR)
std::pair< std::string, data > Decode(const std::string &str)
Decode a Bech32 string.
std::string Encode(const std::string &hrp, const data &values)
Encode a Bech32 string.