Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
utils.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
2 //
3 // SPDX-License-Identifier: LGPL-3.0+
4 
5 #include "libzeth/core/utils.hpp"
6 
7 #include <cassert>
8 #include <stdexcept>
9 
10 namespace libzeth
11 {
12 
13 // Converts a single character to a nibble. Throws std::invalid_argument if the
14 // character is not hex.
15 uint8_t char_to_nibble(const char c)
16 {
17  const char cc = (char)std::tolower(c);
18  if (cc < '0') {
19  throw std::invalid_argument("invalid hex character");
20  }
21  if (cc <= '9') {
22  return cc - '0';
23  }
24  if (cc < 'a') {
25  throw std::invalid_argument("invalid hex character");
26  }
27  if (cc <= 'f') {
28  return cc - 'a' + 10;
29  }
30  throw std::invalid_argument("invalid hex character");
31 }
32 
33 static uint8_t chars_to_byte(const char *cs)
34 {
35  const uint8_t *data = (const uint8_t *)cs;
36  return (char_to_nibble(data[0]) << 4) | char_to_nibble(data[1]);
37 }
38 
39 static char nibble_hex(const uint8_t nibble)
40 {
41  assert((nibble & 0xf0) == 0);
42  if (nibble > 9) {
43  return (char)('a' + nibble - 10);
44  }
45 
46  return (char)('0' + nibble);
47 }
48 
49 // Return a pointer to the beginning of the actual hex characters (removing any
50 // `0x` prefix), and ensure that the length is as expected.
51 static const char *find_hex_string_of_length(
52  const std::string &hex, const size_t bytes)
53 {
54  if ('0' == hex[0] && 'x' == hex[1]) {
55  if (hex.size() != 2 + bytes * 2) {
56  throw std::invalid_argument("invalid hex length");
57  }
58  return hex.c_str() + 2;
59  }
60 
61  if (hex.size() != bytes * 2) {
62  throw std::invalid_argument("invalid hex length");
63  }
64 
65  return hex.c_str();
66 }
67 
68 void hex_to_bytes(const std::string &hex, void *dest, size_t bytes)
69 {
70  const char *cur = find_hex_string_of_length(hex, bytes);
71  uint8_t *dest_bytes = (uint8_t *)dest;
72  const uint8_t *const dest_bytes_end = dest_bytes + bytes;
73  while (dest_bytes < dest_bytes_end) {
74  *dest_bytes = chars_to_byte(cur);
75  cur += 2;
76  ++dest_bytes;
77  }
78 }
79 
80 void hex_to_bytes_reversed(const std::string &hex, void *dest, size_t bytes)
81 {
82  if (bytes == 0) {
83  return;
84  }
85  const char *cur = find_hex_string_of_length(hex, bytes);
86  uint8_t *const dest_bytes_end = (uint8_t *)dest;
87  uint8_t *dest_bytes = dest_bytes_end + bytes;
88  do {
89  --dest_bytes;
90  *dest_bytes = chars_to_byte(cur);
91  cur += 2;
92  } while (dest_bytes > dest_bytes_end);
93 }
94 
95 std::string hex_to_bytes(const std::string &s)
96 {
97  const size_t num_bytes = s.size() / 2;
98  assert(s.size() == 2 * num_bytes);
99  std::string out;
100  out.resize(num_bytes);
101  hex_to_bytes(s, &out[0], num_bytes);
102  return out;
103 }
104 
105 std::string bytes_to_hex(const void *bytes, size_t num_bytes, bool prefix)
106 {
107  std::string out;
108  if (prefix) {
109  out.reserve(num_bytes * 2 + 2);
110  out.push_back('0');
111  out.push_back('x');
112  } else {
113  out.reserve(num_bytes * 2);
114  }
115 
116  const uint8_t *in = (const uint8_t *)bytes;
117  for (size_t i = 0; i < num_bytes; ++i) {
118  const uint8_t byte = in[i];
119  out.push_back(nibble_hex(byte >> 4));
120  out.push_back(nibble_hex(byte & 0x0f));
121  }
122 
123  return out;
124 }
125 
127  const void *bytes, size_t num_bytes, bool prefix)
128 {
129  if (num_bytes == 0) {
130  return "";
131  }
132 
133  std::string out;
134  if (prefix) {
135  out.reserve(num_bytes * 2 + 2);
136  out.push_back('0');
137  out.push_back('x');
138  } else {
139  out.reserve(num_bytes * 2);
140  }
141 
142  const uint8_t *const src_bytes_end = (const uint8_t *)bytes;
143  const uint8_t *src_bytes = src_bytes_end + num_bytes;
144  do {
145  --src_bytes;
146  const uint8_t byte = *src_bytes;
147  out.push_back(nibble_hex(byte >> 4));
148  out.push_back(nibble_hex(byte & 0x0f));
149  } while (src_bytes > src_bytes_end);
150 
151  return out;
152 }
153 
154 } // namespace libzeth
libzeth::hex_to_bytes
void hex_to_bytes(const std::string &hex, void *dest, size_t bytes)
Convert hex to bytes (first chars at lowest address)
Definition: utils.cpp:68
utils.hpp
libzeth
Definition: binary_operation.hpp:15
zeth.core.encryption.bytes
bytes
Definition: encryption.py:87
libzeth::bytes_to_hex_reversed
std::string bytes_to_hex_reversed(const void *bytes, size_t num_bytes, bool prefix)
Definition: utils.cpp:126
libzeth::hex_to_bytes_reversed
void hex_to_bytes_reversed(const std::string &hex, void *dest, size_t bytes)
Definition: utils.cpp:80
libzeth::char_to_nibble
uint8_t char_to_nibble(const char c)
Definition: utils.cpp:15
libzeth::bytes_to_hex
std::string bytes_to_hex(const void *bytes, size_t num_bytes, bool prefix)
Definition: utils.cpp:105
analyzer.parse_r1cs.data
data
Definition: parse_r1cs.py:116