11typedef std::vector<uint8_t> data;
16const char *CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
21const int8_t CHARSET_REV[128] = {
22 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23 -1, -1, -1, -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, 15, -1, 10, 17, 21, 20, 26, 30, 7,
25 5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22,
26 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1,
27 -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0,
28 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1};
35uint64_t PolyMod(
const data &v) {
98 c = ((c & 0x07ffffffff) << 5) ^ d;
147inline uint8_t LowerCase(uint8_t c) {
155data ExpandPrefix(
const std::string &
prefix) {
157 ret.resize(
prefix.size() + 1);
158 for (
size_t i = 0; i <
prefix.size(); ++i) {
159 ret[i] =
prefix[i] & 0x1f;
169bool VerifyChecksum(
const std::string &
prefix,
const data &payload) {
170 return PolyMod(
Cat(ExpandPrefix(
prefix), payload)) == 0;
176data CreateChecksum(
const std::string &
prefix,
const data &payload) {
177 data enc =
Cat(ExpandPrefix(
prefix), payload);
179 enc.resize(enc.size() + 8);
181 uint64_t mod = PolyMod(enc);
183 for (
size_t i = 0; i < 8; ++i) {
185 ret[i] = (mod >> (5 * (7 - i))) & 0x1f;
199 data checksum = CreateChecksum(
prefix, payload);
200 data combined =
Cat(payload, checksum);
201 std::string ret =
prefix +
':';
203 ret.reserve(ret.size() + combined.size());
204 for (uint8_t c : combined) {
214std::pair<std::string, data>
Decode(
const std::string &str,
215 const std::string &default_prefix) {
217 bool lower =
false, upper =
false, hasNumber =
false;
218 size_t prefixSize = 0;
219 for (
size_t i = 0; i < str.size(); ++i) {
221 if (c >=
'a' && c <=
'z') {
226 if (c >=
'A' && c <=
'Z') {
231 if (c >=
'0' && c <=
'9') {
240 if (hasNumber || i == 0 || prefixSize != 0) {
253 if (upper && lower) {
259 if (prefixSize == 0) {
262 prefix.reserve(prefixSize);
263 for (
size_t i = 0; i < prefixSize; ++i) {
264 prefix += LowerCase(str[i]);
272 const size_t valuesSize = str.size() - prefixSize;
273 data values(valuesSize);
274 for (
size_t i = 0; i < valuesSize; ++i) {
275 uint8_t c = str[i + prefixSize];
277 if (c > 127 || CHARSET_REV[c] == -1) {
281 values[i] = CHARSET_REV[c];
285 if (!VerifyChecksum(
prefix, values)) {
289 return {std::move(
prefix), data(values.begin(), values.end() - 8)};
std::pair< std::string, data > Decode(const std::string &str, const std::string &default_prefix)
Decode a cashaddr string.
std::string Encode(const std::string &prefix, const data &payload)
Encode a cashaddr string.
V Cat(V v1, V &&v2)
Concatenate two vectors, moving elements.