From 7ff89fbd17e08208fff7e4d9e8853bc4d1734a34 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 10 Aug 2020 03:51:09 -0700 Subject: [PATCH] ircd: Split base64 and base58 into separate namespaces. --- include/ircd/b58.h | 58 ++++++ include/ircd/b64.h | 81 ++++++++ include/ircd/base.h | 107 ----------- include/ircd/ircd.h | 3 +- ircd/Makefile.am | 5 +- ircd/b58.cc | 164 ++++++++++++++++ ircd/b64.cc | 278 +++++++++++++++++++++++++++ ircd/base.cc | 427 ----------------------------------------- ircd/net.cc | 2 +- matrix/event.cc | 24 +-- matrix/homeserver.cc | 4 +- matrix/id.cc | 6 +- matrix/keys.cc | 10 +- matrix/node.cc | 4 +- matrix/pretty.cc | 2 +- matrix/request.cc | 4 +- matrix/txn.cc | 2 +- matrix/user.cc | 4 +- matrix/user_filter.cc | 2 +- modules/console.cc | 2 +- modules/media/media.cc | 6 +- 21 files changed, 622 insertions(+), 573 deletions(-) create mode 100644 include/ircd/b58.h create mode 100644 include/ircd/b64.h delete mode 100644 include/ircd/base.h create mode 100644 ircd/b58.cc create mode 100644 ircd/b64.cc delete mode 100644 ircd/base.cc diff --git a/include/ircd/b58.h b/include/ircd/b58.h new file mode 100644 index 000000000..9ef5e0806 --- /dev/null +++ b/include/ircd/b58.h @@ -0,0 +1,58 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_B58_H + +namespace ircd::b58 +{ + // Binary -> Base58 encode suite + constexpr size_t encode_size(const size_t &) noexcept; + size_t encode_size(const const_buffer &in) noexcept; + string_view encode(const mutable_buffer &out, const const_buffer &in) noexcept; + + // Base58 -> Binary decode suite + constexpr size_t decode_size(const size_t &) noexcept; + size_t decode_size(const string_view &in) noexcept; + const_buffer decode(const mutable_buffer &out, const string_view &in); + + // Convenience conversions + string_view tob64(const mutable_buffer &out, const string_view &in); + string_view tob64_unpadded(const mutable_buffer &out, const string_view &in); + string_view fromb64(const mutable_buffer &out, const string_view &in); +} + +inline size_t +ircd::b58::decode_size(const string_view &in) +noexcept +{ + return decode_size(size(in)); +} + +constexpr size_t +ircd::b58::decode_size(const size_t &in) +noexcept +{ + return in * 733UL / 1000UL + 1UL; // log(58) / log(256), rounded up +} + +inline size_t +ircd::b58::encode_size(const const_buffer &in) +noexcept +{ + return encode_size(size(in)); +} + +constexpr size_t +ircd::b58::encode_size(const size_t &in) +noexcept +{ + return in * 138UL / 100UL + 1UL; // log(256) / log(58), rounded up +} diff --git a/include/ircd/b64.h b/include/ircd/b64.h new file mode 100644 index 000000000..23cee7d49 --- /dev/null +++ b/include/ircd/b64.h @@ -0,0 +1,81 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_B64_H + +namespace ircd::b64 +{ + extern const u8 + dict_rfc1421[64], // [62] = '+', [63] = '/' + dict_rfc3501[64], // [62] = '+', [63] = ',' + dict_rfc4648[64]; // [62] = '-', [63] = '_' + + // Binary -> Base64 conversion suite + constexpr size_t encode_size(const size_t &) noexcept; + size_t encode_size(const const_buffer &in) noexcept; + string_view encode(const mutable_buffer &out, const const_buffer &in) noexcept; + + // Binary -> Base64 conversion without padding + constexpr size_t encode_unpadded_size(const size_t &) noexcept; + size_t encode_unpadded_size(const const_buffer &in) noexcept; + string_view encode_unpadded(const mutable_buffer &out, const const_buffer &in) noexcept; + + // Base64 -> Binary conversion (padded or unpadded) + constexpr size_t decode_size(const size_t &) noexcept; + size_t decode_size(const string_view &in) noexcept; + const_buffer decode(const mutable_buffer &out, const string_view &in); + + // Base64 convenience conversions + string_view tob64url(const mutable_buffer &out, const string_view &in) noexcept; + string_view urltob64(const mutable_buffer &out, const string_view &in) noexcept; +} + +inline size_t +ircd::b64::decode_size(const string_view &in) +noexcept +{ + return decode_size(size(in)); +} + +constexpr size_t +ircd::b64::decode_size(const size_t &in) +noexcept +{ + return (in * 0.75) + 1; //XXX: constexpr ceil() +} + +inline size_t +ircd::b64::encode_unpadded_size(const const_buffer &in) +noexcept +{ + return encode_unpadded_size(size(in)); +} + +constexpr size_t +ircd::b64::encode_unpadded_size(const size_t &in) +noexcept +{ + return (in * (4.0 / 3.0)) + 1; //XXX: constexpr ceil() +} + +inline size_t +ircd::b64::encode_size(const const_buffer &in) +noexcept +{ + return encode_size(size(in)); +} + +constexpr size_t +ircd::b64::encode_size(const size_t &in) +noexcept +{ + return ((in * (4.0 / 3.0)) + 1) + (3 - in % 3) % 3; //XXX: constexpr ceil +} diff --git a/include/ircd/base.h b/include/ircd/base.h deleted file mode 100644 index 61bb74906..000000000 --- a/include/ircd/base.h +++ /dev/null @@ -1,107 +0,0 @@ -// Matrix Construct -// -// Copyright (C) Matrix Construct Developers, Authors & Contributors -// Copyright (C) 2016-2018 Jason Volk -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice is present in all copies. The -// full license for this software is available in the LICENSE file. - -#pragma once -#define HAVE_IRCD_BASE_H - -namespace ircd -{ - // Binary -> Base58 encode suite - constexpr size_t b58encode_size(const size_t &); - size_t b58encode_size(const const_buffer &in); - string_view b58encode(const mutable_buffer &out, const const_buffer &in) noexcept; - - // Base58 -> Binary decode suite - constexpr size_t b58decode_size(const size_t &); - size_t b58decode_size(const string_view &in); - const_buffer b58decode(const mutable_buffer &out, const string_view &in); - - // Binary -> Base64 conversion suite - constexpr size_t b64encode_size(const size_t &); - size_t b64encode_size(const const_buffer &in); - string_view b64encode(const mutable_buffer &out, const const_buffer &in) noexcept; - - // Binary -> Base64 conversion without padding - constexpr size_t b64encode_unpadded_size(const size_t &); - size_t b64encode_unpadded_size(const const_buffer &in); - string_view b64encode_unpadded(const mutable_buffer &out, const const_buffer &in) noexcept; - - // Base64 -> Binary conversion (padded or unpadded) - constexpr size_t b64decode_size(const size_t &); - size_t b64decode_size(const string_view &in); - const_buffer b64decode(const mutable_buffer &out, const string_view &in); - - // Base64 convenience conversions - string_view b64tob58(const mutable_buffer &out, const string_view &in); - string_view b58tob64(const mutable_buffer &out, const string_view &in); - string_view b58tob64_unpadded(const mutable_buffer &out, const string_view &in); - string_view b64tob64url(const mutable_buffer &out, const string_view &in) noexcept; - string_view b64urltob64(const mutable_buffer &out, const string_view &in) noexcept; -} - -inline size_t -ircd::b64decode_size(const string_view &in) -{ - return b64decode_size(size(in)); -} - -constexpr size_t -ircd::b64decode_size(const size_t &in) -{ - return (in * 0.75) + 1; //XXX: constexpr ceil() -} - -inline size_t -ircd::b64encode_unpadded_size(const const_buffer &in) -{ - return b64encode_unpadded_size(size(in)); -} - -constexpr size_t -ircd::b64encode_unpadded_size(const size_t &in) -{ - return (in * (4.0 / 3.0)) + 1; //XXX: constexpr ceil() -} - -inline size_t -ircd::b64encode_size(const const_buffer &in) -{ - return b64encode_size(size(in)); -} - -constexpr size_t -ircd::b64encode_size(const size_t &in) -{ - return ((in * (4.0 / 3.0)) + 1) + (3 - in % 3) % 3; //XXX: constexpr ceil -} - -inline size_t -ircd::b58decode_size(const string_view &in) -{ - return b58decode_size(size(in)); -} - -constexpr size_t -ircd::b58decode_size(const size_t &in) -{ - return in * 733UL / 1000UL + 1UL; // log(58) / log(256), rounded up -} - -inline size_t -ircd::b58encode_size(const const_buffer &in) -{ - return b58encode_size(size(in)); -} - -constexpr size_t -ircd::b58encode_size(const size_t &in) -{ - return in * 138UL / 100UL + 1UL; // log(256) / log(58), rounded up -} diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index 5d4f3c4a9..8488682cf 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -63,7 +63,8 @@ #include "fpe.h" #include "rand.h" #include "crh.h" -#include "base.h" +#include "b64.h" +#include "b58.h" #include "stringops.h" #include "strl.h" #include "strn.h" diff --git a/ircd/Makefile.am b/ircd/Makefile.am index c1d186b5e..959cc52a4 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -131,7 +131,8 @@ libircd_la_SOURCES += globular.cc libircd_la_SOURCES += tokens.cc libircd_la_SOURCES += parse.cc libircd_la_SOURCES += rand.cc -libircd_la_SOURCES += base.cc +libircd_la_SOURCES += b64.cc +libircd_la_SOURCES += b58.cc libircd_la_SOURCES += crh.cc libircd_la_SOURCES += fmt.cc libircd_la_SOURCES += json.cc @@ -204,7 +205,7 @@ libircd_la_SOURCES += ircd.cc # Specific unit configurations # -base.lo: AM_CPPFLAGS := @BOOST_CPPFLAGS@ ${AM_CPPFLAGS} +b64.lo: AM_CPPFLAGS := @BOOST_CPPFLAGS@ ${AM_CPPFLAGS} client.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS} ctx_x86_64.lo: AM_CPPFLAGS := -I$(top_srcdir)/include ctx.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS} diff --git a/ircd/b58.cc b/ircd/b58.cc new file mode 100644 index 000000000..8cc3f70e8 --- /dev/null +++ b/ircd/b58.cc @@ -0,0 +1,164 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +namespace ircd::b58 +{ + [[gnu::visibility("internal")]] + extern const string_view dict; + + [[gnu::visibility("internal")]] + thread_local char conv_tmp_buf[64_KiB]; +} + +decltype(ircd::b58::dict) +ircd::b58::dict +{ + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"_sv +}; + +// +// Conversion convenience suite +// + +ircd::string_view +ircd::b58::fromb64(const mutable_buffer &out, + const string_view &in) +{ + if(unlikely(b64::decode_size(in) > size(conv_tmp_buf))) + throw error + { + "String too large for conversion at this time." + }; + + return b58::encode(out, b64::decode(conv_tmp_buf, in)); +} + +ircd::string_view +ircd::b58::tob64_unpadded(const mutable_buffer &out, + const string_view &in) +{ + if(unlikely(b58::decode_size(in) > size(conv_tmp_buf))) + throw error + { + "String too large for conversion at this time." + }; + + return b64::encode_unpadded(out, b58::decode(conv_tmp_buf, in)); +} + +ircd::string_view +ircd::b58::tob64(const mutable_buffer &out, + const string_view &in) +{ + if(unlikely(b58::decode_size(in) > size(conv_tmp_buf))) + throw error + { + "String too large for conversion at this time." + }; + + return b64::encode(out, b58::decode(conv_tmp_buf, in)); +} + +// +// Base58 decode +// + +ircd::const_buffer +ircd::b58::decode(const mutable_buffer &buf, + const string_view &in) +{ + auto p(begin(in)); + size_t zeroes(0); + for(; p != end(in) && *p == '1'; ++p) + ++zeroes; + + const mutable_buffer out + { + data(buf) + zeroes, std::min(b58::decode_size(in), size(buf) - zeroes) + }; + + assert(size(out) + zeroes <= size(buf)); + memset(data(out), 0, size(out)); + + size_t length(0); + for(size_t i(0); p != end(in); ++p, length = i, i = 0) + { + auto carry(dict.find(*p)); + if(unlikely(carry == std::string::npos)) + throw std::out_of_range + { + "Invalid base58 character" + }; + + for(auto it(rbegin(out)); (carry || i < length) && it != rend(out); ++it, i++) + { + carry += 58 * (*it); + *it = carry % 256; + carry /= 256; + } + } + + auto it(begin(buf)); + assert(it + zeroes + length <= end(buf)); + for(; it != end(buf) && zeroes; *it++ = 0, --zeroes); + memmove(it, data(out) + (size(out) - length), length); + return const_buffer + { + begin(buf), it + length + }; +} + +// +// Base58 encode +// + +ircd::string_view +ircd::b58::encode(const mutable_buffer &buf, + const const_buffer &in) +noexcept +{ + auto p(begin(in)); + size_t zeroes(0); + for(; p != end(in) && *p == 0; ++p) + ++zeroes; + + const mutable_buffer out + { + data(buf) + zeroes, std::min(b58::encode_size(in), size(buf) - zeroes) + }; + + assert(size(out) + zeroes <= size(buf)); + memset(data(out), 0, size(out)); + + size_t length(0); + for(size_t i(0); p != end(in); ++p, length = i, i = 0) + { + size_t carry(*p); + for(auto it(rbegin(out)); (carry || i < length) && it != rend(out); ++it, i++) + { + carry += 256 * (*it); + *it = carry % 58; + carry /= 58; + } + } + + auto it(begin(buf)); + assert(it + zeroes + length <= end(buf)); + for(; it != end(buf) && zeroes; *it++ = '1', --zeroes); + memmove(it, data(out) + (size(out) - length), length); + return string_view + { + begin(buf), std::transform(it, it + length, it, [] + (const uint8_t &in) + { + return dict.at(in); + }) + }; +} diff --git a/ircd/b64.cc b/ircd/b64.cc new file mode 100644 index 000000000..5c29e9b14 --- /dev/null +++ b/ircd/b64.cc @@ -0,0 +1,278 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#include +#include + +#pragma GCC visibility push(internal) +namespace ircd::b64 +{ + constexpr char pad + { + '=' + }; + + [[gnu::aligned(64)]] + extern const u8 + encode_permute_tab[64], + encode_shift_ctrl[64]; + + static u8x64 encode_block(const u8x64 in) noexcept; +} +#pragma GCC visibility pop + +decltype(ircd::b64::dict_rfc1421) +ircd::b64::dict_rfc1421 +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', +}; + +decltype(ircd::b64::dict_rfc3501) +ircd::b64::dict_rfc3501 +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ',', +}; + +decltype(ircd::b64::dict_rfc4648) +ircd::b64::dict_rfc4648 +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', +}; + +/// For vpermb +/// From arXiv:1910.05109v1 [Mula, Lemire] 2 Oct 2019 +decltype(ircd::b64::encode_permute_tab) +ircd::b64::encode_permute_tab +{ + 0 + 1, 0 + 0, 0 + 2, 0 + 1, 3 + 1, 3 + 0, 3 + 2, 3 + 1, + 6 + 1, 6 + 0, 6 + 2, 6 + 1, 9 + 1, 9 + 0, 9 + 2, 9 + 1, + 12 + 1, 12 + 0, 12 + 2, 12 + 1, 15 + 1, 15 + 0, 15 + 2, 15 + 1, + 18 + 1, 18 + 0, 18 + 2, 18 + 1, 21 + 1, 21 + 0, 21 + 2, 21 + 1, + 24 + 1, 24 + 0, 24 + 2, 24 + 1, 27 + 1, 27 + 0, 27 + 2, 27 + 1, + 30 + 1, 30 + 0, 30 + 2, 30 + 1, 33 + 1, 33 + 0, 33 + 2, 33 + 1, + 36 + 1, 36 + 0, 36 + 2, 36 + 1, 39 + 1, 39 + 0, 39 + 2, 39 + 1, + 42 + 1, 42 + 0, 42 + 2, 42 + 1, 45 + 1, 45 + 0, 45 + 2, 45 + 1, +}; + +/// For vpmultishiftqb +/// From arXiv:1910.05109v1 [Mula, Lemire] 2 Oct 2019 +decltype(ircd::b64::encode_shift_ctrl) +ircd::b64::encode_shift_ctrl +{ + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), + (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), +}; + +// +// Conversion convenience suite +// + +ircd::string_view +ircd::b64::urltob64(const mutable_buffer &out, + const string_view &in) +noexcept +{ + //TODO: optimize with single pass + string_view ret(in); + ret = replace(out, ret, '-', '+'); + ret = replace(out, ret, '_', '/'); + return ret; +} + +ircd::string_view +ircd::b64::tob64url(const mutable_buffer &out, + const string_view &in) +noexcept +{ + //TODO: optimize with single pass + string_view ret(in); + ret = replace(out, ret, '+', '-'); + ret = replace(out, ret, '/', '_'); + return ret; +} + +/// Encoding in to base64 at out. Out must be 1.33+ larger than in +/// padding is not present in the returned view. +ircd::string_view +ircd::b64::encode(const mutable_buffer &out, + const const_buffer &in) +noexcept +{ + const auto pads + { + (3 - size(in) % 3) % 3 + }; + + const auto encoded + { + encode_unpadded(out, in) + }; + + assert(size(encoded) + pads <= size(out)); + memset(data(out) + size(encoded), b64::pad, pads); + + const auto len + { + size(encoded) + pads + }; + + return string_view + { + data(out), len + }; +} + +/// Encoding in to base64 at out. Out must be 1.33+ larger than in. +ircd::string_view +ircd::b64::encode_unpadded(const mutable_buffer &out, + const const_buffer &in) +noexcept +{ + const size_t res_len + { + size_t(ceil(size(in) * (4.0 / 3.0))) + }; + + const size_t out_len + { + std::min(res_len, size(out)) + }; + + size_t i(0), j(0); + for(; i + 1 < (size(in) / 48) && i < (out_len / 64); ++i) + { + // Destination is indexed at 64 byte stride + const auto di + { + reinterpret_cast(data(out) + (i * 64)) + }; + + // Source is indexed at 48 byte stride + const auto si + { + reinterpret_cast(data(in) + (i * 48)) + }; + + *di = encode_block(*si); + } + + for(; i * 48 < size(in); ++i) + { + u8x64 block{0}; + for(j = 0; i * 48 + j < size(in); ++j) + block[j] = in[i * 48 + j]; + + block = encode_block(block); + for(j = 0; i * 64 + j < out_len; ++j) + out[i * 64 + j] = block[j]; + } + + return string_view + { + data(out), out_len + }; +} + +/// Returns 64 base64-encoded characters from 48 input characters. For any +/// inputs less than 48 characters trail with null characters; caller computes +/// result size. The following operations are performed on each triple of input +/// characters resulting in four output characters: +/// 0. in[0] / 4; +/// 1. (in[1] / 16) + ((in[0] * 16) % 64); +/// 2. ((in[1] * 4) % 64) + (in[2] / 64); +/// 3. in[2] % 64; +/// Based on https://arxiv.org/pdf/1910.05109 (and earlier work). No specific +/// intrinsics are used here; instead we recite a kotodama divination known +/// as "vector extensions" which by chance is visible to humans as C syntax. +ircd::u8x64 +ircd::b64::encode_block(const u8x64 in) +noexcept +{ + static const auto &dict + { + dict_rfc1421 + }; + + size_t i, j, k; + + // vpermb + u8x64 _perm; + for(k = 0; k < 64; ++k) + _perm[k] = in[encode_permute_tab[k]]; + + // TODO: currently does not achieve vpmultshiftqb on avx512vbmi + u64x8 sh[8], perm(_perm); + for(i = 0; i < 8; ++i) + for(j = 0; j < 8; ++j) + sh[i][j] = perm[i] >> encode_shift_ctrl[i * 8 + j]; + + // TODO: not needed if vpmultishiftqb is emitted. + for(i = 0; i < 8; ++i) + for(j = 0; j < 8; ++j) + sh[i][j] &= 0x3f; + + u8x64 ret; + for(i = 0, k = 0; i < 8; ++i) + for(j = 0; j < 8; ++j) + ret[k++] = dict[sh[i][j]]; + + return ret; +} + +// +// Base64 decode +// + +/// Decode base64 from in to the buffer at out; out can be 75% of the size +/// of in. +ircd::const_buffer +ircd::b64::decode(const mutable_buffer &out, + const string_view &in) +{ + namespace iterators = boost::archive::iterators; + using b64bf = iterators::binary_from_base64; + using transform = iterators::transform_width; + + const auto pads + { + endswith_count(in, b64::pad) + }; + + const auto e + { + std::copy(transform(begin(in)), transform(begin(in) + size(in) - pads), begin(out)) + }; + + const auto len + { + std::distance(begin(out), e) + }; + + assert(size_t(len) <= size(out)); + return const_buffer + { + data(out), size_t(len) + }; +} diff --git a/ircd/base.cc b/ircd/base.cc deleted file mode 100644 index b49b79636..000000000 --- a/ircd/base.cc +++ /dev/null @@ -1,427 +0,0 @@ -// Matrix Construct -// -// Copyright (C) Matrix Construct Developers, Authors & Contributors -// Copyright (C) 2016-2018 Jason Volk -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice is present in all copies. The -// full license for this software is available in the LICENSE file. - -#include -#include - -namespace ircd::base -{ - [[gnu::visibility("internal")]] - thread_local char conv_tmp_buf[64_KiB]; -} - -// -// Conversion convenience suite -// - -ircd::string_view -ircd::b64urltob64(const mutable_buffer &out, - const string_view &in) -noexcept -{ - //TODO: optimize with single pass - string_view ret(in); - ret = replace(out, ret, '-', '+'); - ret = replace(out, ret, '_', '/'); - return ret; -} - -ircd::string_view -ircd::b64tob64url(const mutable_buffer &out, - const string_view &in) -noexcept -{ - //TODO: optimize with single pass - string_view ret(in); - ret = replace(out, ret, '+', '-'); - ret = replace(out, ret, '/', '_'); - return ret; -} - -ircd::string_view -ircd::b58tob64_unpadded(const mutable_buffer &out, - const string_view &in) -{ - if(unlikely(b58decode_size(in) > size(base::conv_tmp_buf))) - throw error - { - "String too large for conversion at this time." - }; - - return b64encode_unpadded(out, b58decode(base::conv_tmp_buf, in)); -} - -ircd::string_view -ircd::b58tob64(const mutable_buffer &out, - const string_view &in) -{ - if(unlikely(b58decode_size(in) > size(base::conv_tmp_buf))) - throw error - { - "String too large for conversion at this time." - }; - - return b64encode(out, b58decode(base::conv_tmp_buf, in)); -} - -ircd::string_view -ircd::b64tob58(const mutable_buffer &out, - const string_view &in) -{ - if(unlikely(b64decode_size(in) > size(base::conv_tmp_buf))) - throw error - { - "String too large for conversion at this time." - }; - - return b58encode(out, b64decode(base::conv_tmp_buf, in)); -} - -// -// Base64 encode -// - -namespace ircd::base -{ - constexpr char _b64_pad_ - { - '=' - }; - - [[using gnu: visibility("internal"), aligned(64)]] - extern const u8 - b64_encode_permute_tab[64], - b64_encode_shift_ctrl[64]; - - [[using gnu: visibility("internal"), aligned(64)]] - extern const i32 - b64_encode_lut[64]; - - static u8x64 b64encode(const u8x64 in) noexcept; -} - -// [00] - [25] => A - Z -// [26] - [51] => a - z -// [52] - [61] => 0 - 9 -// [62], [63] => +, / -decltype(ircd::base::b64_encode_lut) -ircd::base::b64_encode_lut -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/', -}; - -/// For vpermb -/// From arXiv:1910.05109v1 [Mula, Lemire] 2 Oct 2019 -decltype(ircd::base::b64_encode_permute_tab) -ircd::base::b64_encode_permute_tab -{ - 0 + 1, 0 + 0, 0 + 2, 0 + 1, - 3 + 1, 3 + 0, 3 + 2, 3 + 1, - 6 + 1, 6 + 0, 6 + 2, 6 + 1, - 9 + 1, 9 + 0, 9 + 2, 9 + 1, - 12 + 1, 12 + 0, 12 + 2, 12 + 1, - 15 + 1, 15 + 0, 15 + 2, 15 + 1, - 18 + 1, 18 + 0, 18 + 2, 18 + 1, - 21 + 1, 21 + 0, 21 + 2, 21 + 1, - 24 + 1, 24 + 0, 24 + 2, 24 + 1, - 27 + 1, 27 + 0, 27 + 2, 27 + 1, - 30 + 1, 30 + 0, 30 + 2, 30 + 1, - 33 + 1, 33 + 0, 33 + 2, 33 + 1, - 36 + 1, 36 + 0, 36 + 2, 36 + 1, - 39 + 1, 39 + 0, 39 + 2, 39 + 1, - 42 + 1, 42 + 0, 42 + 2, 42 + 1, - 45 + 1, 45 + 0, 45 + 2, 45 + 1, -}; - -/// For vpmultishiftqb -/// From arXiv:1910.05109v1 [Mula, Lemire] 2 Oct 2019 -decltype(ircd::base::b64_encode_shift_ctrl) -ircd::base::b64_encode_shift_ctrl -{ - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), - (10 + 0), ( 4 + 0), (22 + 0), (16 + 0), - (10 + 32), ( 4 + 32), (22 + 32), (16 + 32), -}; - -/// Encoding in to base64 at out. Out must be 1.33+ larger than in -/// padding is not present in the returned view. -ircd::string_view -ircd::b64encode(const mutable_buffer &out, - const const_buffer &in) -noexcept -{ - const auto pads - { - (3 - size(in) % 3) % 3 - }; - - const auto encoded - { - b64encode_unpadded(out, in) - }; - - assert(size(encoded) + pads <= size(out)); - memset(data(out) + size(encoded), base::_b64_pad_, pads); - - const auto len - { - size(encoded) + pads - }; - - return { data(out), len }; -} - -/// Encoding in to base64 at out. Out must be 1.33+ larger than in. -ircd::string_view -ircd::b64encode_unpadded(const mutable_buffer &out, - const const_buffer &in) -noexcept -{ - const size_t res_len - { - size_t(ceil(size(in) * (4.0 / 3.0))) - }; - - const size_t out_len - { - std::min(res_len, size(out)) - }; - - size_t i(0), j(0); - for(; i + 1 < (size(in) / 48) && i < (out_len / 64); ++i) - { - // Destination is indexed at 64 byte stride - const auto di - { - reinterpret_cast(data(out) + (i * 64)) - }; - - // Source is indexed at 48 byte stride - const auto si - { - reinterpret_cast(data(in) + (i * 48)) - }; - - *di = base::b64encode(*si); - } - - for(; i * 48 < size(in); ++i) - { - u8x64 block{0}; - for(j = 0; i * 48 + j < size(in); ++j) - block[j] = in[i * 48 + j]; - - block = base::b64encode(block); - for(j = 0; i * 64 + j < out_len; ++j) - out[i * 64 + j] = block[j]; - } - - return string_view - { - data(out), out_len - }; -} - -/// Returns 64 base64-encoded characters from 48 input characters. For any -/// inputs less than 48 characters trail with null characters; caller computes -/// result size. The following operations are performed on each triple of input -/// characters resulting in four output characters: -/// 0. in[0] / 4; -/// 1. (in[1] / 16) + ((in[0] * 16) % 64); -/// 2. ((in[1] * 4) % 64) + (in[2] / 64); -/// 3. in[2] % 64; -/// Based on https://arxiv.org/pdf/1910.05109 (and earlier work). No specific -/// intrinsics are used here; instead we recite a kotodama divination known -/// as "vector extensions" which by chance is visible to humans as C syntax. -ircd::u8x64 -ircd::base::b64encode(const u8x64 in) -noexcept -{ - size_t i, j, k; - - // vpermb - u8x64 _perm; - for(k = 0; k < 64; ++k) - _perm[k] = in[b64_encode_permute_tab[k]]; - - // TODO: currently does not achieve vpmultshiftqb on avx512vbmi - u64x8 sh[8], perm(_perm); - for(i = 0; i < 8; ++i) - for(j = 0; j < 8; ++j) - sh[i][j] = perm[i] >> b64_encode_shift_ctrl[i * 8 + j]; - - // TODO: not needed if vpmultishiftqb is emitted. - for(i = 0; i < 8; ++i) - for(j = 0; j < 8; ++j) - sh[i][j] &= 0x3f; - - u8x64 ret; - for(i = 0, k = 0; i < 8; ++i) - for(j = 0; j < 8; ++j) - ret[k++] = b64_encode_lut[sh[i][j]]; - - return ret; -} - -// -// Base64 decode -// - -/// Decode base64 from in to the buffer at out; out can be 75% of the size -/// of in. -ircd::const_buffer -ircd::b64decode(const mutable_buffer &out, - const string_view &in) -{ - namespace iterators = boost::archive::iterators; - using b64bf = iterators::binary_from_base64; - using transform = iterators::transform_width; - - const auto pads - { - endswith_count(in, base::_b64_pad_) - }; - - const auto e - { - std::copy(transform(begin(in)), transform(begin(in) + size(in) - pads), begin(out)) - }; - - const auto len - { - std::distance(begin(out), e) - }; - - assert(size_t(len) <= size(out)); - return { data(out), size_t(len) }; -} - -// -// Base58 -// - -namespace ircd::base -{ - static const auto &b58 - { - "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"s - }; -} - -// -// Base58 decode -// - -ircd::const_buffer -ircd::b58decode(const mutable_buffer &buf, - const string_view &in) -{ - auto p(begin(in)); - size_t zeroes(0); - for(; p != end(in) && *p == '1'; ++p) - ++zeroes; - - const mutable_buffer out - { - data(buf) + zeroes, std::min(b58decode_size(in), size(buf) - zeroes) - }; - - assert(size(out) + zeroes <= size(buf)); - memset(data(out), 0, size(out)); - - size_t length(0); - for(size_t i(0); p != end(in); ++p, length = i, i = 0) - { - auto carry(base::b58.find(*p)); - if(carry == std::string::npos) - throw std::out_of_range("Invalid base58 character"); - - for(auto it(rbegin(out)); (carry || i < length) && it != rend(out); ++it, i++) - { - carry += 58 * (*it); - *it = carry % 256; - carry /= 256; - } - } - - auto it(begin(buf)); - assert(it + zeroes + length <= end(buf)); - for(; it != end(buf) && zeroes; *it++ = 0, --zeroes); - memmove(it, data(out) + (size(out) - length), length); - return { begin(buf), it + length }; -} - -// -// Base58 encode -// - -ircd::string_view -ircd::b58encode(const mutable_buffer &buf, - const const_buffer &in) -noexcept -{ - auto p(begin(in)); - size_t zeroes(0); - for(; p != end(in) && *p == 0; ++p) - ++zeroes; - - const mutable_buffer out - { - data(buf) + zeroes, std::min(b58encode_size(in), size(buf) - zeroes) - }; - - assert(size(out) + zeroes <= size(buf)); - memset(data(out), 0, size(out)); - - size_t length(0); - for(size_t i(0); p != end(in); ++p, length = i, i = 0) - { - size_t carry(*p); - for(auto it(rbegin(out)); (carry || i < length) && it != rend(out); ++it, i++) - { - carry += 256 * (*it); - *it = carry % 58; - carry /= 58; - } - } - - auto it(begin(buf)); - assert(it + zeroes + length <= end(buf)); - for(; it != end(buf) && zeroes; *it++ = '1', --zeroes); - memmove(it, data(out) + (size(out) - length), length); - return - { - begin(buf), std::transform(it, it + length, it, [] - (const uint8_t &in) - { - return base::b58.at(in); - }) - }; -} diff --git a/ircd/net.cc b/ircd/net.cc index 56f6ba542..1d4fbbb18 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -123,7 +123,7 @@ ircd::net::peer_cert_der_sha256_b64(const mutable_buffer &buf, peer_cert_der_sha256(shabuf, socket) }; - return b64encode_unpadded(buf, hash); + return b64::encode_unpadded(buf, hash); } ircd::const_buffer diff --git a/matrix/event.cc b/matrix/event.cc index a4f55ef5d..d925d8c2b 100644 --- a/matrix/event.cc +++ b/matrix/event.cc @@ -107,13 +107,13 @@ ircd::m::make_id(const event &event, id::event::buf &buf, const const_buffer &hash) { - char readable[b64encode_size(sha256::digest_size)]; + char readable[b64::encode_size(sha256::digest_size)]; if(version == "1" || version == "2") { const id::event ret { - buf, b64tob64url(readable, b64encode_unpadded(readable, hash)), at<"origin"_>(event) + buf, b64::tob64url(readable, b64::encode_unpadded(readable, hash)), at<"origin"_>(event) }; buf.assigned(ret); @@ -123,7 +123,7 @@ ircd::m::make_id(const event &event, { const id::event ret { - buf, b64encode_unpadded(readable, hash), string_view{} + buf, b64::encode_unpadded(readable, hash), string_view{} }; buf.assigned(ret); @@ -132,7 +132,7 @@ ircd::m::make_id(const event &event, const id::event ret { - buf, b64tob64url(readable, b64encode_unpadded(readable, hash)), string_view{} + buf, b64::tob64url(readable, b64::encode_unpadded(readable, hash)), string_view{} }; buf.assigned(ret); @@ -168,11 +168,11 @@ ircd::json::object ircd::m::make_hashes(const mutable_buffer &out, const sha256::buf &hash) { - static const auto b64bufsz(b64encode_size(sizeof(hash))); + static const auto b64bufsz(b64::encode_size(sizeof(hash))); thread_local char hashb64buf[b64bufsz]; const json::members hashes { - { "sha256", b64encode_unpadded(hashb64buf, hash) } + { "sha256", b64::encode_unpadded(hashb64buf, hash) } }; return json::stringify(mutable_buffer{out}, hashes); @@ -245,7 +245,7 @@ ircd::m::verify_hash(const event &event, }; thread_local char b64buf[hashb64sz]; - return verify_sha256b64(event, b64encode_unpadded(b64buf, hash)); + return verify_sha256b64(event, b64::encode_unpadded(b64buf, hash)); } bool @@ -290,10 +290,10 @@ ircd::m::event::signatures(const mutable_buffer &out, m::public_key_id(m::my(origin)) }; - thread_local char sigb64buf[b64encode_size(sizeof(sig))]; + thread_local char sigb64buf[b64::encode_size(sizeof(sig))]; const json::members sigb64 { - { public_key_id, b64encode_unpadded(sigb64buf, sig) } + { public_key_id, b64::encode_unpadded(sigb64buf, sig) } }; const json::members sigs @@ -350,7 +350,7 @@ ircd::m::signatures(const mutable_buffer &out_, static const auto sigb64bufsz { - b64encode_size(sizeof(my_sig)) + b64::encode_size(sizeof(my_sig)) }; thread_local char sigb64buf[sigb64bufsz]; @@ -358,7 +358,7 @@ ircd::m::signatures(const mutable_buffer &out_, { origin, json::members { - { public_key_id, b64encode_unpadded(sigb64buf, my_sig) } + { public_key_id, b64::encode_unpadded(sigb64buf, my_sig) } } }; @@ -600,7 +600,7 @@ ircd::m::verify(const event &event, { [&origin_sigs, &keyid](auto &buf) { - b64decode(buf, json::string(origin_sigs.at(keyid))); + b64::decode(buf, json::string(origin_sigs.at(keyid))); } }; diff --git a/matrix/homeserver.cc b/matrix/homeserver.cc index de4f8620f..8d415a754 100644 --- a/matrix/homeserver.cc +++ b/matrix/homeserver.cc @@ -384,7 +384,7 @@ ircd::m::homeserver::key::key(const struct opts &opts) { ircd::string(96, [this](const mutable_buffer &buf) { - return b64encode_unpadded(buf, public_key); + return b64::encode_unpadded(buf, public_key); }) } ,public_key_id @@ -433,7 +433,7 @@ ircd::m::homeserver::key::key(const struct opts &opts) { { opts.origin, json::member { - public_key_id, b64encode_unpadded(buf[1], sig) + public_key_id, b64::encode_unpadded(buf[1], sig) }} }) }; diff --git a/matrix/id.cc b/matrix/id.cc index 0d9d2ee46..7fd84be22 100644 --- a/matrix/id.cc +++ b/matrix/id.cc @@ -793,7 +793,7 @@ ircd::m::id::event::v3::v3(const mutable_buffer &out, out[0] = '$'; const string_view hashb64 { - b64encode_unpadded(out + 1, hash) + b64::encode_unpadded(out + 1, hash) }; return string_view @@ -863,8 +863,8 @@ ircd::m::id::event::v4::v4(const mutable_buffer &out, out[0] = '$'; string_view hashb64; - hashb64 = b64encode_unpadded(out + 1, hash); - hashb64 = b64tob64url(out + 1, hashb64); + hashb64 = b64::encode_unpadded(out + 1, hash); + hashb64 = b64::tob64url(out + 1, hashb64); return string_view { ircd::data(out), 1 + ircd::size(hashb64) diff --git a/matrix/keys.cc b/matrix/keys.cc index d889ec237..e6571de94 100644 --- a/matrix/keys.cc +++ b/matrix/keys.cc @@ -123,7 +123,7 @@ ircd::m::verify(const m::keys &keys) { [&key](auto &pk) { - b64decode(pk, unquote(key.at("key"))); + b64::decode(pk, unquote(key.at("key"))); } }; @@ -146,7 +146,7 @@ ircd::m::verify(const m::keys &keys) { [&server_signatures, &key_id](auto &sig) { - b64decode(sig, unquote(server_signatures.at(key_id))); + b64::decode(sig, unquote(server_signatures.at(key_id))); } }; @@ -639,7 +639,7 @@ noexcept try char seed_buf[ed25519::SEED_SZ + 10]; const auto seed { - b64decode(seed_buf, "YJDBA9Xnr2sVqXD9Vj7XVUnmFZcZrlw8Md7kMW+3XA1") + b64::decode(seed_buf, "YJDBA9Xnr2sVqXD9Vj7XVUnmFZcZrlw8Md7kMW+3XA1") }; ed25519::pk pk; @@ -659,12 +659,12 @@ noexcept try char sigb64_buf[128]; const auto sigb64 { - b64encode_unpadded(sigb64_buf, sig) + b64::encode_unpadded(sigb64_buf, sig) }; ed25519::sig unsig; const auto unsigb64 { - b64decode(unsig, sigb64) + b64::decode(unsig, sigb64) }; return pk.verify(const_buffer{object}, unsig); diff --git a/matrix/node.cc b/matrix/node.cc index 842864f19..0635fa915 100644 --- a/matrix/node.cc +++ b/matrix/node.cc @@ -77,7 +77,7 @@ ircd::m::node::room::room(const m::node &node) const string_view b58 { - b58encode(buf, hash) + b58::encode(buf, hash) }; return id::room::buf @@ -105,7 +105,7 @@ const { [&keyb64](auto &buf) { - b64decode(buf, keyb64); + b64::decode(buf, keyb64); } }; diff --git a/matrix/pretty.cc b/matrix/pretty.cc index 24290e544..e95f4c09e 100644 --- a/matrix/pretty.cc +++ b/matrix/pretty.cc @@ -166,7 +166,7 @@ ircd::m::pretty_detailed(std::ostream &out, char buf[512]; out << std::setw(9) << std::left << "!!! ERROR" << " " - << "HASH MISMATCH :" << b64encode_unpadded(buf, hash(event)) + << "HASH MISMATCH :" << b64::encode_unpadded(buf, hash(event)) << std::endl; } diff --git a/matrix/request.cc b/matrix/request.cc index 3e4f3826a..3e9171604 100644 --- a/matrix/request.cc +++ b/matrix/request.cc @@ -208,7 +208,7 @@ const out, "X-Matrix origin=%s,key=\"%s\",sig=\"%s\"", origin, pkid, - b64encode_unpadded(sigb64, sig) + b64::encode_unpadded(sigb64, sig) }; } @@ -221,7 +221,7 @@ const { [&sig_](auto &buf) { - b64decode(buf, sig_); + b64::decode(buf, sig_); } }; diff --git a/matrix/txn.cc b/matrix/txn.cc index 50bf24305..2644b9e73 100644 --- a/matrix/txn.cc +++ b/matrix/txn.cc @@ -132,7 +132,7 @@ ircd::m::txn::create_id(const mutable_buffer &out, const string_view txnid { - b58encode(out, hash) + b58::encode(out, hash) }; return txnid; diff --git a/matrix/user.cc b/matrix/user.cc index 0e4cd38fa..e91c2c9bf 100644 --- a/matrix/user.cc +++ b/matrix/user.cc @@ -145,7 +145,7 @@ const char b58[size(hash) * 2]; return { - buf, b58encode(b58, hash), origin(my()) + buf, b58::encode(b58, hash), origin(my()) }; } @@ -258,7 +258,7 @@ ircd::m::gen_password_hash(const mutable_buffer &out, sha256{supplied_password} }; - return b64encode_unpadded(out, hash); + return b64::encode_unpadded(out, hash); } // diff --git a/matrix/user_filter.cc b/matrix/user_filter.cc index cac58b10d..8ad5d89b8 100644 --- a/matrix/user_filter.cc +++ b/matrix/user_filter.cc @@ -33,7 +33,7 @@ ircd::m::user::filter::set(const mutable_buffer &idbuf, const string_view filter_id { - b64tob64url(idbuf, b64encode_unpadded(idbuf, hash)) + b64::tob64url(idbuf, b64::encode_unpadded(idbuf, hash)) }; //TODO: ABA diff --git a/modules/console.cc b/modules/console.cc index de131209f..9c3bd120c 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -6895,7 +6895,7 @@ console_cmd__stage(opt &out, const string_view &line) { char buf[512]; if(!verify_hash(event)) - out << "- HASH MISMATCH: " << b64encode_unpadded(buf, hash(event)) << std::endl; + out << "- HASH MISMATCH: " << b64::encode_unpadded(buf, hash(event)) << std::endl; } catch(const std::exception &e) { diff --git a/modules/media/media.cc b/modules/media/media.cc index 1bcec86bd..1c0aee66d 100644 --- a/modules/media/media.cc +++ b/modules/media/media.cc @@ -615,7 +615,7 @@ ircd::m::media::file::room_id(room::id::buf &out, out = { - b58encode(buf, hash), my_host() + b58::encode(buf, hash), my_host() }; return out; @@ -633,7 +633,7 @@ ircd::m::media::block::set(const m::room &room, { static constexpr const auto bufsz { - b58encode_size(sha256::digest_size) + b58::encode_size(sha256::digest_size) }; char b58buf[bufsz]; @@ -661,7 +661,7 @@ ircd::m::media::block::set(const mutable_buffer &b58buf, const string_view b58hash { - b58encode(b58buf, hash) + b58::encode(b58buf, hash) }; set(b58hash, block);