cchecksum 0.0.1__py2.py3-none-any.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.
Potentially problematic release.
This version of cchecksum might be problematic. Click here for more details.
- cchecksum/__init__.py +2 -0
- cchecksum/_cchecksum.pyi +3 -0
- cchecksum/_checksum.pyx +54 -0
- cchecksum/checksum.py +111 -0
- cchecksum/py.typed +0 -0
- cchecksum-0.0.1.dist-info/METADATA +16 -0
- cchecksum-0.0.1.dist-info/RECORD +8 -0
- cchecksum-0.0.1.dist-info/WHEEL +4 -0
cchecksum/__init__.py
ADDED
cchecksum/_cchecksum.pyi
ADDED
cchecksum/_checksum.pyx
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
def cchecksum(str norm_address_no_0x, str address_hash_hex_no_0x) -> str:
|
|
2
|
+
"""
|
|
3
|
+
Computes the checksummed version of an Ethereum address.
|
|
4
|
+
|
|
5
|
+
This function takes a normalized Ethereum address (without the '0x' prefix) and its corresponding
|
|
6
|
+
hash (also without the '0x' prefix) and returns the checksummed address as per the Ethereum
|
|
7
|
+
Improvement Proposal 55 (EIP-55).
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
norm_address_no_0x (str): The normalized Ethereum address without the '0x' prefix.
|
|
11
|
+
address_hash_hex_no_0x (str): The hash of the address, also without the '0x' prefix.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
The checksummed Ethereum address with the '0x' prefix.
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
>>> cchecksum("b47e3cd837ddf8e4c57f05d70ab865de6e193bbb", "abcdef1234567890abcdef1234567890abcdef12")
|
|
18
|
+
'0xB47E3Cd837DdF8E4C57F05D70Ab865De6E193BbB'
|
|
19
|
+
|
|
20
|
+
>>> cchecksum("0000000000000000000000000000000000000000", "1234567890abcdef1234567890abcdef12345678")
|
|
21
|
+
'0x0000000000000000000000000000000000000000'
|
|
22
|
+
|
|
23
|
+
See Also:
|
|
24
|
+
- :func:`eth_utils.to_checksum_address`: A utility function for converting addresses to their checksummed form.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# Declare memoryviews for fixed-length data
|
|
28
|
+
cdef unsigned char[::1] norm_address_mv = bytearray(norm_address_no_0x.encode('ascii'))
|
|
29
|
+
cdef unsigned char[::1] hash_bytes_mv = bytearray(address_hash_hex_no_0x.encode('ascii'))
|
|
30
|
+
|
|
31
|
+
# Create a buffer for our result
|
|
32
|
+
# 2 for "0x" prefix and 40 for the address itself
|
|
33
|
+
cdef unsigned char[42] buffer = b'0x' + bytearray(40)
|
|
34
|
+
|
|
35
|
+
# Handle character casing based on the hash value
|
|
36
|
+
cdef int i
|
|
37
|
+
cdef int address_char
|
|
38
|
+
|
|
39
|
+
for i in range(40):
|
|
40
|
+
address_char = norm_address_mv[i]
|
|
41
|
+
|
|
42
|
+
if hash_bytes_mv[i] < 56:
|
|
43
|
+
# '0' to '7' have ASCII values 48 to 55
|
|
44
|
+
buffer[i + 2] = address_char
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
# This checks if `norm_char` falls in the ASCII range for lowercase hexadecimal
|
|
48
|
+
# characters ('a' to 'f'), which correspond to ASCII values 97 to 102. If it does,
|
|
49
|
+
# the character is capitalized.
|
|
50
|
+
buffer[i + 2] = address_char - 32 if 97 <= address_char <= 102 else address_char
|
|
51
|
+
|
|
52
|
+
# NOTE: For some reason on some systems the buffer length is longer than 42 here, even though that should not be possible.
|
|
53
|
+
# Lucky for us, the first 42 characters are always correct. One day maybe I'll debug this.
|
|
54
|
+
return bytes(buffer[:42]).decode('ascii')
|
cchecksum/checksum.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import binascii
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from eth_typing import AnyAddress, ChecksumAddress, HexAddress
|
|
5
|
+
from eth_utils import hexstr_if_str, keccak, to_hex
|
|
6
|
+
from eth_utils.address import _HEX_ADDRESS_REGEXP
|
|
7
|
+
|
|
8
|
+
from cchecksum._checksum import cchecksum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# this was ripped out of eth_utils and optimized a little bit
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def to_checksum_address(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress:
|
|
15
|
+
"""
|
|
16
|
+
Convert an address to its EIP-55 checksum format.
|
|
17
|
+
|
|
18
|
+
This function takes an address in any supported format and returns it in the
|
|
19
|
+
checksummed format as defined by EIP-55. It uses a custom Cython implementation
|
|
20
|
+
for the checksum conversion to optimize performance.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
value: The address to be converted. It can be in any format supported by
|
|
24
|
+
:func:`eth_utils.to_normalized_address`.
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
ValueError: If the input address is not in a recognized format.
|
|
28
|
+
TypeError: If the input is not a string, bytes, or any address type.
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
>>> to_checksum_address("0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb")
|
|
32
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
33
|
+
|
|
34
|
+
>>> to_checksum_address(b'\xb4~<\xd87\xdd\xf8\xe4\xc5\x7f\x05\xd7\n\xb8e\xden\x19;\xbb')
|
|
35
|
+
'0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'
|
|
36
|
+
|
|
37
|
+
See Also:
|
|
38
|
+
- :func:`eth_utils.to_checksum_address` for the standard implementation.
|
|
39
|
+
- :func:`to_normalized_address` for converting to a normalized address before checksumming.
|
|
40
|
+
"""
|
|
41
|
+
norm_address_no_0x = to_normalized_address(value)[2:]
|
|
42
|
+
address_hash = keccak(text=norm_address_no_0x)
|
|
43
|
+
address_hash_hex_no_0x = binascii.hexlify(address_hash).decode("ascii")
|
|
44
|
+
return cchecksum(norm_address_no_0x, address_hash_hex_no_0x)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def to_normalized_address(value: Union[AnyAddress, str, bytes]) -> HexAddress:
|
|
48
|
+
"""
|
|
49
|
+
Converts an address to its normalized hexadecimal representation.
|
|
50
|
+
|
|
51
|
+
This function ensures that the address is in a consistent lowercase hexadecimal
|
|
52
|
+
format, which is useful for further processing or validation. It uses
|
|
53
|
+
:func:`eth_utils.hexstr_if_str` and :func:`eth_utils.to_hex` to convert the input
|
|
54
|
+
to a hexadecimal string.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
value: The address to be normalized. It can be in any format supported by
|
|
58
|
+
:func:`eth_utils.to_hex`.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ValueError: If the input address is not in a recognized format.
|
|
62
|
+
TypeError: If the input is not a string, bytes, or any address type.
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
>>> to_normalized_address("0xB47E3CD837DDF8E4C57F05D70AB865DE6E193BBB")
|
|
66
|
+
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb'
|
|
67
|
+
|
|
68
|
+
>>> to_normalized_address(b'\xb4~<\xd87\xdd\xf8\xe4\xc5\x7f\x05\xd7\n\xb8e\xden\x19;\xbb')
|
|
69
|
+
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb'
|
|
70
|
+
|
|
71
|
+
See Also:
|
|
72
|
+
- :func:`eth_utils.to_normalized_address` for the standard implementation.
|
|
73
|
+
- :func:`is_address` for checking if a string is a valid address.
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
hex_address = hexstr_if_str(to_hex, value).lower()
|
|
77
|
+
except AttributeError:
|
|
78
|
+
raise TypeError(f"Value must be any string, instead got type {type(value)}")
|
|
79
|
+
|
|
80
|
+
if not is_address(hex_address):
|
|
81
|
+
raise ValueError(
|
|
82
|
+
f"Unknown format {repr(value)}, attempted to normalize to {repr(hex_address)}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return hex_address # type: ignore [return-value]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def is_address(value: str) -> bool:
|
|
89
|
+
"""
|
|
90
|
+
Check if the given string is a valid address in any known format.
|
|
91
|
+
|
|
92
|
+
This function uses a regular expression to determine if the input string
|
|
93
|
+
matches the expected pattern for a hexadecimal address.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
value: The string to be checked.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
True if the string is a valid address, False otherwise.
|
|
100
|
+
|
|
101
|
+
Examples:
|
|
102
|
+
>>> is_address("0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb")
|
|
103
|
+
True
|
|
104
|
+
|
|
105
|
+
>>> is_address("not-an-address")
|
|
106
|
+
False
|
|
107
|
+
|
|
108
|
+
See Also:
|
|
109
|
+
- :func:`eth_utils.is_address` for the standard implementation.
|
|
110
|
+
"""
|
|
111
|
+
return _HEX_ADDRESS_REGEXP.fullmatch(value) is not None
|
cchecksum/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cchecksum
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A ~2x faster drop-in replacement for eth_utils.to_checksum_address. Raises the exact same Exceptions. Implemented in C.
|
|
5
|
+
Classifier: Programming Language :: Python :: 2
|
|
6
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.4
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
cchecksum/__init__.py,sha256=9-zGSD00qMygcrDHsETJUjNxiEez2yfWTKevEdAV2aU,84
|
|
2
|
+
cchecksum/_cchecksum.pyi,sha256=W_5hkOKIW7HMcNQEvtWd3hBq7NQSsLpirjvC5bnNuYw,134
|
|
3
|
+
cchecksum/_checksum.pyx,sha256=G65TQEozxbVTq9AgSKLLA9xfjmCl8AwbZYoFrJyvS3U,2459
|
|
4
|
+
cchecksum/checksum.py,sha256=YvnNt8Sg2-sqoeQfJTSnu1vxlM03-TIwUaQUP9asWGw,4039
|
|
5
|
+
cchecksum/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
cchecksum-0.0.1.dist-info/METADATA,sha256=HHfHEFzwrTqX6JKy3qIGGYblld4bkz11ah7cETN0rVk,781
|
|
7
|
+
cchecksum-0.0.1.dist-info/WHEEL,sha256=IrRNNNJ-uuL1ggO5qMvT1GGhQVdQU54d6ZpYqEZfEWo,92
|
|
8
|
+
cchecksum-0.0.1.dist-info/RECORD,,
|