#ifndef BTCEXPLORER_HASH_H #define BTCEXPLORER_HASH_H #include #include #include #include #include #include namespace hash { static const char hex_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static const uint8_t base58map[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; // Generalization of something acting as contiguous sequence of bytes // For example: std::array, std::vector, std::span template concept ByteArray = requires(T collection) { { collection[0] } -> std::same_as; { collection.size() } -> std::same_as; { collection.data() } -> std::same_as; requires sizeof(typename T::value_type) == 1; }; template std::string to_string(const T& data) { std::string str(data.size()*2, ' '); for(size_t i = 0; i < data.size(); ++i) { str[2*i] = hex_table[(data[i] & 0xF0) >> 4]; str[2*i + 1] = hex_table[data[i] & 0x0F]; } return str; } template std::string to_string_inverse(const T& data) { const size_t stringSize = data.size()*2; std::string str(stringSize, ' '); for(size_t i = 0; i < data.size(); ++i) { str[stringSize - 2 - 2*i] = hex_table[(data[i] & 0xF0) >> 4]; str[stringSize - 1 - 2*i] = hex_table[data[i] & 0x0F]; } return str; } template std::array sha256(const T& data) { std::array hash{}; SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, data.data(), data.size()); SHA256_Final(hash.data(), &ctx); return hash; } template std::array ripemd160(const T& data) { std::array hash{}; RIPEMD160_CTX ctx; RIPEMD160_Init(&ctx); RIPEMD160_Update(&ctx, data.data(), data.size()); RIPEMD160_Final(hash.data(), &ctx); return hash; } template std::array ripemd160(const T& data, uint8_t prefix) { std::array hash{}; hash[0] = prefix; RIPEMD160_CTX ctx; RIPEMD160_Init(&ctx); RIPEMD160_Update(&ctx, data.data(), data.size()); RIPEMD160_Final(hash.data() + 1, &ctx); return hash; } template std::array hash160(const T& data) { return ripemd160(sha256(data)); } template std::array hash160(const T& data, uint8_t prefix) { return ripemd160(sha256(data), prefix); } template std::array hash256(const T& data) { return sha256(sha256(data)); } template std::string base58(const T& data) { std::vector digits((data.size() * 138 / 100) + 1); size_t digitsLen = 1; for (size_t i = 0; i < data.size(); i++) { uint32_t carry = static_cast(data[i]); for (size_t j = 0; j < digitsLen; j++) { carry = carry + static_cast(digits[j] << 8); digits[j] = static_cast(carry % 58); carry /= 58; } for (; carry; carry /= 58) digits[digitsLen++] = static_cast(carry % 58); } std::string result; for (size_t i = 0; i < (data.size() - 1) && !data[i]; i++) result.push_back(base58map[0]); for (size_t i = 0; i < digitsLen; i++) result.push_back(base58map[digits[digitsLen - 1 - i]]); return result; } } #endif //BTCEXPLORER_HASH_H