cchecksum 0.4.0__cp312-cp312-musllinux_1_2_i686.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- benchmarks/__init__.py +0 -0
- benchmarks/data.py +70 -0
- benchmarks/test_checksum_benchmarks.py +23 -0
- cchecksum/__init__.py +15 -0
- cchecksum/_checksum.c +32263 -0
- cchecksum/_checksum.cpython-312-i386-linux-musl.so +0 -0
- cchecksum/_checksum.pyi +72 -0
- cchecksum/_checksum.pyx +549 -0
- cchecksum/keccak.c +127 -0
- cchecksum/keccak.h +8 -0
- cchecksum/monkey_patch.py +47 -0
- cchecksum/py.typed +0 -0
- cchecksum-0.4.0.dist-info/METADATA +50 -0
- cchecksum-0.4.0.dist-info/RECORD +17 -0
- cchecksum-0.4.0.dist-info/WHEEL +5 -0
- cchecksum-0.4.0.dist-info/licenses/LICENSE +21 -0
- cchecksum-0.4.0.dist-info/top_level.txt +2 -0
|
Binary file
|
cchecksum/_checksum.pyi
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from eth_typing import AnyAddress, ChecksumAddress, HexAddress
|
|
2
|
+
from typing import Iterable, List, Union
|
|
3
|
+
|
|
4
|
+
def to_checksum_address(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress:
|
|
5
|
+
"""
|
|
6
|
+
Convert an address to its EIP-55 checksum format.
|
|
7
|
+
|
|
8
|
+
This function takes an address in any supported format and returns it in the
|
|
9
|
+
checksummed format as defined by EIP-55. It uses a custom Cython implementation
|
|
10
|
+
for the checksum conversion to optimize performance.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
value: The address to be converted. It can be in any format supported by
|
|
14
|
+
:func:`eth_utils.to_normalized_address`.
|
|
15
|
+
|
|
16
|
+
Raises:
|
|
17
|
+
ValueError: If the input address is not in a recognized format.
|
|
18
|
+
TypeError: If the input is not a string, bytes, or any address type.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
>>> to_checksum_address("0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb")
|
|
22
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
23
|
+
|
|
24
|
+
>>> to_checksum_address(b'\xb4~<\xd87\xdd\xf8\xe4\xc5\x7f\x05\xd7\n\xb8e\xden\x19;\xbb')
|
|
25
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
26
|
+
|
|
27
|
+
See Also:
|
|
28
|
+
- :func:`eth_utils.to_checksum_address` for the standard implementation.
|
|
29
|
+
- :func:`to_normalized_address` for converting to a normalized address before checksumming.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def to_checksum_address_many(
|
|
33
|
+
values: Union[
|
|
34
|
+
bytes,
|
|
35
|
+
bytearray,
|
|
36
|
+
memoryview,
|
|
37
|
+
Iterable[Union[AnyAddress, str, bytes, bytearray]],
|
|
38
|
+
],
|
|
39
|
+
) -> List[ChecksumAddress]:
|
|
40
|
+
"""
|
|
41
|
+
Convert multiple addresses to EIP-55 checksum format.
|
|
42
|
+
|
|
43
|
+
Accepts a sequence of address-like inputs (str/bytes/bytearray) or a packed
|
|
44
|
+
bytes-like object containing concatenated 20-byte addresses.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def to_normalized_address_no_0x(value: Union[AnyAddress, str, bytes]) -> bytes:
|
|
48
|
+
"""
|
|
49
|
+
Converts an address to its normalized hexadecimal representation without the '0x' prefix.
|
|
50
|
+
|
|
51
|
+
This function ensures that the address is in a consistent lowercase hexadecimal
|
|
52
|
+
format, which is useful for further processing or validation.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
value: The address to be normalized.
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
ValueError: If the input address is not in a recognized format.
|
|
59
|
+
TypeError: If the input is not a string, bytes, or any address type.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
>>> to_normalized_address("0xB47E3CD837DDF8E4C57F05D70AB865DE6E193BBB")
|
|
63
|
+
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb'
|
|
64
|
+
|
|
65
|
+
>>> to_normalized_address(b'\xb4~<\xd87\xdd\xf8\xe4\xc5\x7f\x05\xd7\n\xb8e\xden\x19;\xbb')
|
|
66
|
+
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb'
|
|
67
|
+
|
|
68
|
+
See Also:
|
|
69
|
+
- :func:`eth_utils.to_normalized_address` for the standard implementation.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def cchecksum(norm_address_no_0x: bytes, address_hash_hex_no_0x: bytes) -> ChecksumAddress: ...
|
cchecksum/_checksum.pyx
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
# cython: boundscheck=False
|
|
2
|
+
# cython: wraparound=False
|
|
3
|
+
|
|
4
|
+
from cpython.bytes cimport PyBytes_GET_SIZE
|
|
5
|
+
from cpython.sequence cimport PySequence_Fast, PySequence_Fast_GET_ITEM, PySequence_Fast_GET_SIZE
|
|
6
|
+
from cpython.unicode cimport PyUnicode_AsEncodedString, PyUnicode_DecodeASCII
|
|
7
|
+
from cython.parallel cimport prange
|
|
8
|
+
from libc.stddef cimport size_t
|
|
9
|
+
from libc.string cimport memcpy
|
|
10
|
+
|
|
11
|
+
from eth_typing import AnyAddress, ChecksumAddress
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
cdef const unsigned char* hexdigits = b"0123456789abcdef"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# this was ripped out of eth_utils and optimized a little bit
|
|
18
|
+
|
|
19
|
+
cdef extern from "keccak.h":
|
|
20
|
+
void keccak_256(const unsigned char* data, size_t len, unsigned char* out) nogil
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
cpdef unicode to_checksum_address(value: Union[AnyAddress, str, bytes]):
|
|
24
|
+
"""
|
|
25
|
+
Convert an address to its EIP-55 checksum format.
|
|
26
|
+
|
|
27
|
+
This function takes an address in any supported format and returns it in the
|
|
28
|
+
checksummed format as defined by EIP-55. It uses a custom Cython implementation
|
|
29
|
+
for the checksum conversion to optimize performance.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
value: The address to be converted. It can be in any format supported by
|
|
33
|
+
:func:`eth_utils.to_normalized_address`.
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
ValueError: If the input address is not in a recognized format.
|
|
37
|
+
TypeError: If the input is not a string, bytes, or any address type.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
>>> to_checksum_address("0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb")
|
|
41
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
42
|
+
|
|
43
|
+
>>> to_checksum_address(b'\xb4~<\xd87\xdd\xf8\xe4\xc5\x7f\x05\xd7\n\xb8e\xden\x19;\xbb')
|
|
44
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
45
|
+
|
|
46
|
+
See Also:
|
|
47
|
+
- :func:`eth_utils.to_checksum_address` for the standard implementation.
|
|
48
|
+
- :func:`to_normalized_address` for converting to a normalized address before checksumming.
|
|
49
|
+
"""
|
|
50
|
+
cdef bytes hex_address_bytes
|
|
51
|
+
cdef const unsigned char* hex_address_bytestr
|
|
52
|
+
cdef unsigned char c
|
|
53
|
+
cdef unsigned char hash_out[32]
|
|
54
|
+
|
|
55
|
+
cdef unsigned char hash_buffer[80]
|
|
56
|
+
|
|
57
|
+
# Create a buffer for our result
|
|
58
|
+
# 2 for "0x" prefix and 40 for the address itself
|
|
59
|
+
cdef char result_buffer[42]
|
|
60
|
+
result_buffer[0] = 48 # '0'
|
|
61
|
+
result_buffer[1] = 120 # 'x'
|
|
62
|
+
|
|
63
|
+
if isinstance(value, str):
|
|
64
|
+
hex_address_bytes = lowercase_ascii_and_validate(PyUnicode_AsEncodedString(value, b"ascii", NULL))
|
|
65
|
+
hex_address_bytestr = hex_address_bytes
|
|
66
|
+
|
|
67
|
+
elif isinstance(value, (bytes, bytearray)):
|
|
68
|
+
hex_address_bytes = hexlify(value)
|
|
69
|
+
hex_address_bytestr = hex_address_bytes
|
|
70
|
+
num_bytes = PyBytes_GET_SIZE(hex_address_bytes)
|
|
71
|
+
|
|
72
|
+
with nogil:
|
|
73
|
+
for i in range(num_bytes):
|
|
74
|
+
c = hex_address_bytestr[i]
|
|
75
|
+
|
|
76
|
+
if not is_hex_lower(c):
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"Unknown format {repr(value)}, attempted to normalize to '0x{hex_address_bytes.decode()}'"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
else:
|
|
82
|
+
raise TypeError(
|
|
83
|
+
f"Unsupported type: '{repr(type(value))}'. Must be one of: bool, str, bytes, bytearray or int."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if PyBytes_GET_SIZE(hex_address_bytes) != 40:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
f"Unknown format {repr(value)}, attempted to normalize to '0x{hex_address_bytes.decode()}'"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
with nogil:
|
|
92
|
+
keccak_256(hex_address_bytestr, 40, hash_out)
|
|
93
|
+
hexlify_c_string_to_buffer(hash_out, hash_buffer, 32)
|
|
94
|
+
populate_result_buffer(result_buffer, hex_address_bytestr, hash_buffer)
|
|
95
|
+
|
|
96
|
+
# It is faster to decode a buffer with a known size ie buffer[:42]
|
|
97
|
+
return result_buffer[:42].decode('ascii')
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
cpdef list to_checksum_address_many(object values):
|
|
101
|
+
"""
|
|
102
|
+
Convert multiple addresses to EIP-55 checksum format.
|
|
103
|
+
|
|
104
|
+
Accepts a sequence of address-like inputs (str/bytes/bytearray) or a packed
|
|
105
|
+
bytes-like object containing concatenated 20-byte addresses.
|
|
106
|
+
"""
|
|
107
|
+
cdef Py_ssize_t i, n, packed_len
|
|
108
|
+
cdef bytes hex_address_bytes
|
|
109
|
+
cdef const unsigned char* hex_address_bytestr
|
|
110
|
+
cdef object item
|
|
111
|
+
cdef object seq
|
|
112
|
+
cdef const unsigned char[:] packed_view
|
|
113
|
+
cdef const unsigned char* packed_ptr
|
|
114
|
+
cdef unsigned char* norm_ptr
|
|
115
|
+
cdef unsigned char* hash_ptr
|
|
116
|
+
cdef char* result_ptr
|
|
117
|
+
cdef bytearray norm_hex
|
|
118
|
+
cdef bytearray hashes
|
|
119
|
+
cdef bytearray results
|
|
120
|
+
cdef list output
|
|
121
|
+
|
|
122
|
+
if isinstance(values, (bytes, bytearray, memoryview)):
|
|
123
|
+
packed_view = values
|
|
124
|
+
|
|
125
|
+
if packed_view.ndim != 1 or packed_view.itemsize != 1 or packed_view.strides[0] != 1:
|
|
126
|
+
raise TypeError("Packed addresses must be a contiguous 1-D view of bytes.")
|
|
127
|
+
|
|
128
|
+
packed_len = packed_view.shape[0]
|
|
129
|
+
if packed_len % 20 != 0:
|
|
130
|
+
raise ValueError("Packed address bytes length must be a multiple of 20.")
|
|
131
|
+
|
|
132
|
+
n = packed_len // 20
|
|
133
|
+
if n == 0:
|
|
134
|
+
return []
|
|
135
|
+
|
|
136
|
+
norm_hex = bytearray(n * 40)
|
|
137
|
+
hashes = bytearray(n * 32)
|
|
138
|
+
results = bytearray(n * 42)
|
|
139
|
+
norm_ptr = norm_hex
|
|
140
|
+
hash_ptr = hashes
|
|
141
|
+
result_ptr = results
|
|
142
|
+
packed_ptr = &packed_view[0]
|
|
143
|
+
|
|
144
|
+
with nogil:
|
|
145
|
+
for i in range(n):
|
|
146
|
+
hexlify_c_string_to_buffer(packed_ptr + (i * 20), norm_ptr + (i * 40), 20)
|
|
147
|
+
|
|
148
|
+
for i in prange(n, schedule="static"):
|
|
149
|
+
keccak_256(norm_ptr + (i * 40), 40, hash_ptr + (i * 32))
|
|
150
|
+
checksum_address_to_buffer(
|
|
151
|
+
result_ptr + (i * 42),
|
|
152
|
+
norm_ptr + (i * 40),
|
|
153
|
+
hash_ptr + (i * 32),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
output = [None] * n
|
|
157
|
+
for i in range(n):
|
|
158
|
+
output[i] = PyUnicode_DecodeASCII(result_ptr + (i * 42), 42, NULL)
|
|
159
|
+
return output
|
|
160
|
+
|
|
161
|
+
if isinstance(values, str):
|
|
162
|
+
raise TypeError("to_checksum_address_many expects a sequence of addresses, not a str.")
|
|
163
|
+
|
|
164
|
+
seq = PySequence_Fast(values, "to_checksum_address_many expects a sequence of addresses.")
|
|
165
|
+
n = PySequence_Fast_GET_SIZE(seq)
|
|
166
|
+
if n == 0:
|
|
167
|
+
return []
|
|
168
|
+
|
|
169
|
+
norm_hex = bytearray(n * 40)
|
|
170
|
+
hashes = bytearray(n * 32)
|
|
171
|
+
results = bytearray(n * 42)
|
|
172
|
+
norm_ptr = norm_hex
|
|
173
|
+
hash_ptr = hashes
|
|
174
|
+
result_ptr = results
|
|
175
|
+
|
|
176
|
+
for i in range(n):
|
|
177
|
+
item = <object>PySequence_Fast_GET_ITEM(seq, i)
|
|
178
|
+
|
|
179
|
+
if isinstance(item, str):
|
|
180
|
+
hex_address_bytes = lowercase_ascii_and_validate(PyUnicode_AsEncodedString(item, b"ascii", NULL))
|
|
181
|
+
hex_address_bytestr = hex_address_bytes
|
|
182
|
+
elif isinstance(item, (bytes, bytearray)):
|
|
183
|
+
hex_address_bytes = hexlify(item)
|
|
184
|
+
hex_address_bytestr = hex_address_bytes
|
|
185
|
+
else:
|
|
186
|
+
raise TypeError(
|
|
187
|
+
f"Unsupported type: '{repr(type(item))}'. Must be one of: bool, str, bytes, bytearray or int."
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if PyBytes_GET_SIZE(hex_address_bytes) != 40:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
f"Unknown format {repr(item)}, attempted to normalize to '0x{hex_address_bytes.decode()}'"
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
memcpy(norm_ptr + (i * 40), hex_address_bytestr, 40)
|
|
196
|
+
|
|
197
|
+
with nogil:
|
|
198
|
+
for i in prange(n, schedule="static"):
|
|
199
|
+
keccak_256(norm_ptr + (i * 40), 40, hash_ptr + (i * 32))
|
|
200
|
+
checksum_address_to_buffer(
|
|
201
|
+
result_ptr + (i * 42),
|
|
202
|
+
norm_ptr + (i * 40),
|
|
203
|
+
hash_ptr + (i * 32),
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
output = [None] * n
|
|
207
|
+
for i in range(n):
|
|
208
|
+
output[i] = PyUnicode_DecodeASCII(result_ptr + (i * 42), 42, NULL)
|
|
209
|
+
return output
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
cpdef bytes hexlify(const unsigned char[:] src_buffer):
|
|
213
|
+
return bytes(hexlify_unsafe(src_buffer, len(src_buffer)))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
cdef const unsigned char[:] hexlify_unsafe(const unsigned char[:] src_buffer, Py_ssize_t num_bytes) noexcept:
|
|
217
|
+
"""Make sure your `num_bytes` is correct or ting go boom"""
|
|
218
|
+
cdef unsigned char[:] result_buffer = bytearray(num_bytes * 2) # contiguous and writeable
|
|
219
|
+
with nogil:
|
|
220
|
+
hexlify_memview_to_buffer(src_buffer, result_buffer, num_bytes)
|
|
221
|
+
return result_buffer
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
cdef inline void hexlify_memview_to_buffer(
|
|
225
|
+
const unsigned char[:] src_buffer,
|
|
226
|
+
unsigned char[:] result_buffer,
|
|
227
|
+
Py_ssize_t num_bytes,
|
|
228
|
+
) noexcept nogil:
|
|
229
|
+
cdef Py_ssize_t i
|
|
230
|
+
cdef unsigned char c
|
|
231
|
+
for i in range(num_bytes):
|
|
232
|
+
c = src_buffer[i]
|
|
233
|
+
result_buffer[2*i] = hexdigits[c >> 4]
|
|
234
|
+
result_buffer[2*i+1] = hexdigits[c & 0x0F]
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
cdef inline void hexlify_c_string_to_buffer(
|
|
238
|
+
const unsigned char* src_buffer,
|
|
239
|
+
unsigned char* result_buffer,
|
|
240
|
+
Py_ssize_t num_bytes,
|
|
241
|
+
) noexcept nogil:
|
|
242
|
+
cdef Py_ssize_t i
|
|
243
|
+
cdef unsigned char c
|
|
244
|
+
for i in range(num_bytes):
|
|
245
|
+
c = src_buffer[i]
|
|
246
|
+
result_buffer[2*i] = hexdigits[c >> 4]
|
|
247
|
+
result_buffer[2*i+1] = hexdigits[c & 0x0F]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
cdef inline void checksum_address_to_buffer(
|
|
251
|
+
char* buffer,
|
|
252
|
+
const unsigned char* norm_address_no_0x,
|
|
253
|
+
const unsigned char* address_hash_bytes,
|
|
254
|
+
) noexcept nogil:
|
|
255
|
+
cdef Py_ssize_t i
|
|
256
|
+
cdef unsigned char hash_byte
|
|
257
|
+
cdef unsigned char hash_nibble
|
|
258
|
+
cdef unsigned char c
|
|
259
|
+
|
|
260
|
+
buffer[0] = 48 # '0'
|
|
261
|
+
buffer[1] = 120 # 'x'
|
|
262
|
+
|
|
263
|
+
for i in range(40):
|
|
264
|
+
c = norm_address_no_0x[i]
|
|
265
|
+
hash_byte = address_hash_bytes[i >> 1]
|
|
266
|
+
if i & 1:
|
|
267
|
+
hash_nibble = hash_byte & 0x0F
|
|
268
|
+
else:
|
|
269
|
+
hash_nibble = hash_byte >> 4
|
|
270
|
+
if hash_nibble < 8:
|
|
271
|
+
buffer[i + 2] = c
|
|
272
|
+
else:
|
|
273
|
+
buffer[i + 2] = get_char(c)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
cdef void populate_result_buffer(
|
|
277
|
+
char[42] buffer,
|
|
278
|
+
const unsigned char* norm_address_no_0x,
|
|
279
|
+
const unsigned char* address_hash_hex_no_0x,
|
|
280
|
+
) noexcept nogil:
|
|
281
|
+
"""
|
|
282
|
+
Computes the checksummed version of an Ethereum address.
|
|
283
|
+
|
|
284
|
+
This function takes a normalized Ethereum address (without the '0x' prefix) and its corresponding
|
|
285
|
+
hash (also without the '0x' prefix) and returns the checksummed address as per the Ethereum
|
|
286
|
+
Improvement Proposal 55 (EIP-55).
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
norm_address_no_0x: The normalized Ethereum address without the '0x' prefix.
|
|
290
|
+
address_hash_hex_no_0x: The hash of the address, also without the '0x' prefix.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
The checksummed Ethereum address with the '0x' prefix.
|
|
294
|
+
|
|
295
|
+
See Also:
|
|
296
|
+
- :func:`eth_utils.to_checksum_address`: A utility function for converting addresses to their checksummed form.
|
|
297
|
+
"""
|
|
298
|
+
# Handle character casing based on the hash value
|
|
299
|
+
# `if address_hash_hex_no_0x[x] < 56`
|
|
300
|
+
# '0' to '7' have ASCII values 48 to 55
|
|
301
|
+
if address_hash_hex_no_0x[0] < 56:
|
|
302
|
+
buffer[2] = norm_address_no_0x[0]
|
|
303
|
+
else:
|
|
304
|
+
buffer[2] = get_char(norm_address_no_0x[0])
|
|
305
|
+
if address_hash_hex_no_0x[1] < 56:
|
|
306
|
+
buffer[3] = norm_address_no_0x[1]
|
|
307
|
+
else:
|
|
308
|
+
buffer[3] = get_char(norm_address_no_0x[1])
|
|
309
|
+
if address_hash_hex_no_0x[2] < 56:
|
|
310
|
+
buffer[4] = norm_address_no_0x[2]
|
|
311
|
+
else:
|
|
312
|
+
buffer[4] = get_char(norm_address_no_0x[2])
|
|
313
|
+
if address_hash_hex_no_0x[3] < 56:
|
|
314
|
+
buffer[5] = norm_address_no_0x[3]
|
|
315
|
+
else:
|
|
316
|
+
buffer[5] = get_char(norm_address_no_0x[3])
|
|
317
|
+
if address_hash_hex_no_0x[4] < 56:
|
|
318
|
+
buffer[6] = norm_address_no_0x[4]
|
|
319
|
+
else:
|
|
320
|
+
buffer[6] = get_char(norm_address_no_0x[4])
|
|
321
|
+
if address_hash_hex_no_0x[5] < 56:
|
|
322
|
+
buffer[7] = norm_address_no_0x[5]
|
|
323
|
+
else:
|
|
324
|
+
buffer[7] = get_char(norm_address_no_0x[5])
|
|
325
|
+
if address_hash_hex_no_0x[6] < 56:
|
|
326
|
+
buffer[8] = norm_address_no_0x[6]
|
|
327
|
+
else:
|
|
328
|
+
buffer[8] = get_char(norm_address_no_0x[6])
|
|
329
|
+
if address_hash_hex_no_0x[7] < 56:
|
|
330
|
+
buffer[9] = norm_address_no_0x[7]
|
|
331
|
+
else:
|
|
332
|
+
buffer[9] = get_char(norm_address_no_0x[7])
|
|
333
|
+
if address_hash_hex_no_0x[8] < 56:
|
|
334
|
+
buffer[10] = norm_address_no_0x[8]
|
|
335
|
+
else:
|
|
336
|
+
buffer[10] = get_char(norm_address_no_0x[8])
|
|
337
|
+
if address_hash_hex_no_0x[9] < 56:
|
|
338
|
+
buffer[11] = norm_address_no_0x[9]
|
|
339
|
+
else:
|
|
340
|
+
buffer[11] = get_char(norm_address_no_0x[9])
|
|
341
|
+
if address_hash_hex_no_0x[10] < 56:
|
|
342
|
+
buffer[12] = norm_address_no_0x[10]
|
|
343
|
+
else:
|
|
344
|
+
buffer[12] = get_char(norm_address_no_0x[10])
|
|
345
|
+
if address_hash_hex_no_0x[11] < 56:
|
|
346
|
+
buffer[13] = norm_address_no_0x[11]
|
|
347
|
+
else:
|
|
348
|
+
buffer[13] = get_char(norm_address_no_0x[11])
|
|
349
|
+
if address_hash_hex_no_0x[12] < 56:
|
|
350
|
+
buffer[14] = norm_address_no_0x[12]
|
|
351
|
+
else:
|
|
352
|
+
buffer[14] = get_char(norm_address_no_0x[12])
|
|
353
|
+
if address_hash_hex_no_0x[13] < 56:
|
|
354
|
+
buffer[15] = norm_address_no_0x[13]
|
|
355
|
+
else:
|
|
356
|
+
buffer[15] = get_char(norm_address_no_0x[13])
|
|
357
|
+
if address_hash_hex_no_0x[14] < 56:
|
|
358
|
+
buffer[16] = norm_address_no_0x[14]
|
|
359
|
+
else:
|
|
360
|
+
buffer[16] = get_char(norm_address_no_0x[14])
|
|
361
|
+
if address_hash_hex_no_0x[15] < 56:
|
|
362
|
+
buffer[17] = norm_address_no_0x[15]
|
|
363
|
+
else:
|
|
364
|
+
buffer[17] = get_char(norm_address_no_0x[15])
|
|
365
|
+
if address_hash_hex_no_0x[16] < 56:
|
|
366
|
+
buffer[18] = norm_address_no_0x[16]
|
|
367
|
+
else:
|
|
368
|
+
buffer[18] = get_char(norm_address_no_0x[16])
|
|
369
|
+
if address_hash_hex_no_0x[17] < 56:
|
|
370
|
+
buffer[19] = norm_address_no_0x[17]
|
|
371
|
+
else:
|
|
372
|
+
buffer[19] = get_char(norm_address_no_0x[17])
|
|
373
|
+
if address_hash_hex_no_0x[18] < 56:
|
|
374
|
+
buffer[20] = norm_address_no_0x[18]
|
|
375
|
+
else:
|
|
376
|
+
buffer[20] = get_char(norm_address_no_0x[18])
|
|
377
|
+
if address_hash_hex_no_0x[19] < 56:
|
|
378
|
+
buffer[21] = norm_address_no_0x[19]
|
|
379
|
+
else:
|
|
380
|
+
buffer[21] = get_char(norm_address_no_0x[19])
|
|
381
|
+
if address_hash_hex_no_0x[20] < 56:
|
|
382
|
+
buffer[22] = norm_address_no_0x[20]
|
|
383
|
+
else:
|
|
384
|
+
buffer[22] = get_char(norm_address_no_0x[20])
|
|
385
|
+
if address_hash_hex_no_0x[21] < 56:
|
|
386
|
+
buffer[23] = norm_address_no_0x[21]
|
|
387
|
+
else:
|
|
388
|
+
buffer[23] = get_char(norm_address_no_0x[21])
|
|
389
|
+
if address_hash_hex_no_0x[22] < 56:
|
|
390
|
+
buffer[24] = norm_address_no_0x[22]
|
|
391
|
+
else:
|
|
392
|
+
buffer[24] = get_char(norm_address_no_0x[22])
|
|
393
|
+
if address_hash_hex_no_0x[23] < 56:
|
|
394
|
+
buffer[25] = norm_address_no_0x[23]
|
|
395
|
+
else:
|
|
396
|
+
buffer[25] = get_char(norm_address_no_0x[23])
|
|
397
|
+
if address_hash_hex_no_0x[24] < 56:
|
|
398
|
+
buffer[26] = norm_address_no_0x[24]
|
|
399
|
+
else:
|
|
400
|
+
buffer[26] = get_char(norm_address_no_0x[24])
|
|
401
|
+
if address_hash_hex_no_0x[25] < 56:
|
|
402
|
+
buffer[27] = norm_address_no_0x[25]
|
|
403
|
+
else:
|
|
404
|
+
buffer[27] = get_char(norm_address_no_0x[25])
|
|
405
|
+
if address_hash_hex_no_0x[26] < 56:
|
|
406
|
+
buffer[28] = norm_address_no_0x[26]
|
|
407
|
+
else:
|
|
408
|
+
buffer[28] = get_char(norm_address_no_0x[26])
|
|
409
|
+
if address_hash_hex_no_0x[27] < 56:
|
|
410
|
+
buffer[29] = norm_address_no_0x[27]
|
|
411
|
+
else:
|
|
412
|
+
buffer[29] = get_char(norm_address_no_0x[27])
|
|
413
|
+
if address_hash_hex_no_0x[28] < 56:
|
|
414
|
+
buffer[30] = norm_address_no_0x[28]
|
|
415
|
+
else:
|
|
416
|
+
buffer[30] = get_char(norm_address_no_0x[28])
|
|
417
|
+
if address_hash_hex_no_0x[29] < 56:
|
|
418
|
+
buffer[31] = norm_address_no_0x[29]
|
|
419
|
+
else:
|
|
420
|
+
buffer[31] = get_char(norm_address_no_0x[29])
|
|
421
|
+
if address_hash_hex_no_0x[30] < 56:
|
|
422
|
+
buffer[32] = norm_address_no_0x[30]
|
|
423
|
+
else:
|
|
424
|
+
buffer[32] = get_char(norm_address_no_0x[30])
|
|
425
|
+
if address_hash_hex_no_0x[31] < 56:
|
|
426
|
+
buffer[33] = norm_address_no_0x[31]
|
|
427
|
+
else:
|
|
428
|
+
buffer[33] = get_char(norm_address_no_0x[31])
|
|
429
|
+
if address_hash_hex_no_0x[32] < 56:
|
|
430
|
+
buffer[34] = norm_address_no_0x[32]
|
|
431
|
+
else:
|
|
432
|
+
buffer[34] = get_char(norm_address_no_0x[32])
|
|
433
|
+
if address_hash_hex_no_0x[33] < 56:
|
|
434
|
+
buffer[35] = norm_address_no_0x[33]
|
|
435
|
+
else:
|
|
436
|
+
buffer[35] = get_char(norm_address_no_0x[33])
|
|
437
|
+
if address_hash_hex_no_0x[34] < 56:
|
|
438
|
+
buffer[36] = norm_address_no_0x[34]
|
|
439
|
+
else:
|
|
440
|
+
buffer[36] = get_char(norm_address_no_0x[34])
|
|
441
|
+
if address_hash_hex_no_0x[35] < 56:
|
|
442
|
+
buffer[37] = norm_address_no_0x[35]
|
|
443
|
+
else:
|
|
444
|
+
buffer[37] = get_char(norm_address_no_0x[35])
|
|
445
|
+
if address_hash_hex_no_0x[36] < 56:
|
|
446
|
+
buffer[38] = norm_address_no_0x[36]
|
|
447
|
+
else:
|
|
448
|
+
buffer[38] = get_char(norm_address_no_0x[36])
|
|
449
|
+
if address_hash_hex_no_0x[37] < 56:
|
|
450
|
+
buffer[39] = norm_address_no_0x[37]
|
|
451
|
+
else:
|
|
452
|
+
buffer[39] = get_char(norm_address_no_0x[37])
|
|
453
|
+
if address_hash_hex_no_0x[38] < 56:
|
|
454
|
+
buffer[40] = norm_address_no_0x[38]
|
|
455
|
+
else:
|
|
456
|
+
buffer[40] = get_char(norm_address_no_0x[38])
|
|
457
|
+
if address_hash_hex_no_0x[39] < 56:
|
|
458
|
+
buffer[41] = norm_address_no_0x[39]
|
|
459
|
+
else:
|
|
460
|
+
buffer[41] = get_char(norm_address_no_0x[39])
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
cdef inline unsigned char get_char(unsigned char c) noexcept nogil:
|
|
464
|
+
"""This checks if `address_char` falls in the ASCII range for lowercase hexadecimal
|
|
465
|
+
characters ('a' to 'f'), which correspond to ASCII values 97 to 102. If it does,
|
|
466
|
+
the character is capitalized.
|
|
467
|
+
"""
|
|
468
|
+
if c == 97: # a
|
|
469
|
+
return 65 # A
|
|
470
|
+
elif c == 98: # b
|
|
471
|
+
return 66 # B
|
|
472
|
+
elif c == 99: # c
|
|
473
|
+
return 67 # C
|
|
474
|
+
elif c == 100: # d
|
|
475
|
+
return 68 # D
|
|
476
|
+
elif c == 101: # e
|
|
477
|
+
return 69 # E
|
|
478
|
+
elif c == 102: # f
|
|
479
|
+
return 70 # F
|
|
480
|
+
else:
|
|
481
|
+
return c
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
cdef inline bint is_hex_lower(unsigned char c) noexcept nogil:
|
|
485
|
+
return (48 <= c <= 57) or (97 <= c <= 102)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
cdef unsigned char* lowercase_ascii_and_validate(bytes src):
|
|
489
|
+
cdef Py_ssize_t src_len, range_start, i
|
|
490
|
+
cdef unsigned char* c_string
|
|
491
|
+
cdef unsigned char c
|
|
492
|
+
|
|
493
|
+
src_len = PyBytes_GET_SIZE(src)
|
|
494
|
+
c_string = src
|
|
495
|
+
|
|
496
|
+
with nogil:
|
|
497
|
+
# if c_string[0] == b"0" and c_string[1] in (b"X", b"x")
|
|
498
|
+
if c_string[0] == 48 and c_string[1] in (88, 120):
|
|
499
|
+
range_start = 2
|
|
500
|
+
else:
|
|
501
|
+
range_start = 0
|
|
502
|
+
|
|
503
|
+
for i in range(range_start, src_len):
|
|
504
|
+
c = c_string[i]
|
|
505
|
+
|
|
506
|
+
if 65 <= c <= 90:
|
|
507
|
+
c += 32
|
|
508
|
+
c_string[i] = c
|
|
509
|
+
|
|
510
|
+
if c == 48: # 0
|
|
511
|
+
pass
|
|
512
|
+
elif c == 49: # 1
|
|
513
|
+
pass
|
|
514
|
+
elif c == 50: # 2
|
|
515
|
+
pass
|
|
516
|
+
elif c == 51: # 3
|
|
517
|
+
pass
|
|
518
|
+
elif c == 52: # 4
|
|
519
|
+
pass
|
|
520
|
+
elif c == 53: # 5
|
|
521
|
+
pass
|
|
522
|
+
elif c == 54: # 6
|
|
523
|
+
pass
|
|
524
|
+
elif c == 55: # 7
|
|
525
|
+
pass
|
|
526
|
+
elif c == 56: # 8
|
|
527
|
+
pass
|
|
528
|
+
elif c == 57: # 9
|
|
529
|
+
pass
|
|
530
|
+
elif c == 97: # a
|
|
531
|
+
pass
|
|
532
|
+
elif c == 98: # b
|
|
533
|
+
pass
|
|
534
|
+
elif c == 99: # c
|
|
535
|
+
pass
|
|
536
|
+
elif c == 100: # d
|
|
537
|
+
pass
|
|
538
|
+
elif c == 101: # e
|
|
539
|
+
pass
|
|
540
|
+
elif c == 102: # f
|
|
541
|
+
pass
|
|
542
|
+
else:
|
|
543
|
+
with gil:
|
|
544
|
+
raise ValueError("when sending a str, it must be a hex string. " f"Got: {repr(src.decode('ascii'))}")
|
|
545
|
+
|
|
546
|
+
return c_string[range_start:]
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
del AnyAddress, ChecksumAddress
|