Kagome
Polkadot Runtime Engine in C++17
ss58_codec.cpp
Go to the documentation of this file.
1 
7 
8 #include <libp2p/multi/multibase_codec/codecs/base58.hpp>
9 
10 #include "crypto/hasher.hpp"
11 
14 
15  switch (e) {
16  case E::INVALID_LENGTH:
17  return "Invalid SS58 address length; Only 35 byte addresses are "
18  "supported";
19  case E::INVALID_CHECKSUM:
20  return "Invalid SS58 checksum";
21  }
22  return "Unknown SS58 codec error";
23 }
24 
25 namespace kagome::primitives {
26 
28  gsl::span<uint8_t, kSs58Length - kSs58ChecksumLength> ss58_address,
29  const crypto::Hasher &hasher) {
30  constexpr auto PREFIX = "SS58PRE";
31  auto preimage = common::Buffer{}.put(PREFIX).put(ss58_address);
32  auto checksum = hasher.blake2b_512(preimage);
33  return common::Buffer{
34  gsl::make_span(checksum).subspan(0, kSs58ChecksumLength)};
35  }
36 
37  outcome::result<AccountId> decodeSs58(std::string_view account_address,
38  const crypto::Hasher &hasher) noexcept {
39  // decode SS58 address: base58(<address-type><address><checksum>)
40  // https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
41  OUTCOME_TRY(ss58_account_id,
42  libp2p::multi::detail::decodeBase58(account_address));
43  primitives::AccountId account_id;
44 
45  // first byte in SS58 is account type, then 32 bytes of the actual account
46  // id, then 2 bytes of checksum
47  if (ss58_account_id.size() != kSs58Length) {
49  }
50 
51  auto ss58_no_checksum = gsl::make_span(
52  ss58_account_id.data(), ss58_account_id.size() - kSs58ChecksumLength);
53  auto checksum = gsl::make_span<const uint8_t>(
54  ss58_account_id.data() + ss58_no_checksum.size(), kSs58ChecksumLength);
55  auto calculated_checksum = calculateChecksum(ss58_no_checksum, hasher);
56  if (gsl::span<const uint8_t>(calculated_checksum) != checksum) {
58  }
59 
60  std::copy_n(ss58_account_id.begin() + 1,
61  primitives::AccountId::size(),
62  account_id.begin());
63 
64  return account_id;
65  }
66 
67  std::string encodeSs58(uint8_t account_type,
68  const AccountId &id,
69  const crypto::Hasher &hasher) noexcept {
70  common::Buffer ss58_bytes;
71  ss58_bytes.reserve(kSs58Length);
72  ss58_bytes.putUint8(account_type).put(id);
73  auto checksum = calculateChecksum(ss58_bytes, hasher);
74  ss58_bytes.put(checksum);
75 
76  return libp2p::multi::detail::encodeBase58(ss58_bytes.asVector());
77  }
78 
79 } // namespace kagome::primitives
Class represents arbitrary (including empty) byte buffer.
Definition: buffer.hpp:29
const std::vector< uint8_t > & asVector() const
getter for vector of bytes
Definition: buffer.hpp:135
virtual Hash512 blake2b_512(gsl::span< const uint8_t > buffer) const =0
blake2b_512 function calculates 64-byte blake2b hash
static common::Buffer calculateChecksum(gsl::span< uint8_t, kSs58Length-kSs58ChecksumLength > ss58_address, const crypto::Hasher &hasher)
Definition: ss58_codec.cpp:27
constexpr size_t kSs58Length
Definition: ss58_codec.hpp:23
gsl::span< const uint8_t > make_span(const rocksdb::Slice &s)
SLBuffer & put(std::string_view view)
Put a string into byte buffer.
Definition: buffer.hpp:117
OUTCOME_CPP_DEFINE_CATEGORY(kagome::primitives, Ss58Error, e)
Definition: ss58_codec.cpp:12
SLBuffer & reserve(size_t size)
Definition: buffer.hpp:61
outcome::result< AccountId > decodeSs58(std::string_view account_address, const crypto::Hasher &hasher) noexcept
Definition: ss58_codec.cpp:37
SLBuffer & putUint8(uint8_t n)
Put a 8-bit {.
Definition: buffer.hpp:79
crypto::Sr25519PublicKey AccountId
Definition: account.hpp:13
std::string encodeSs58(uint8_t account_type, const AccountId &id, const crypto::Hasher &hasher) noexcept
Definition: ss58_codec.cpp:67
constexpr size_t kSs58ChecksumLength
Definition: ss58_codec.hpp:22