Skip to content

Commit 935bca3

Browse files
CodeAgentCNCodeAgentCN
andauthored
chore: add type hints (#157)
Co-authored-by: CodeAgentCN <codeagentcn@protonmail.com>
1 parent d92445c commit 935bca3

12 files changed

Lines changed: 180 additions & 114 deletions

File tree

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
include_package_data=True,
4747
install_requires=[
4848
"eth-hash>=0.1.0",
49+
"eth-typing>=2.0.0,<3",
4950
"eth-utils>=2.0.0",
5051
"hexbytes>=0.2.3",
5152
"rlp>=3",

trie/binary.py

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
from typing import (
2+
Any,
3+
Dict,
4+
Iterator,
5+
List,
6+
Optional,
7+
Sequence,
8+
Tuple,
9+
Union,
10+
)
11+
112
from eth_hash.auto import (
213
keccak,
314
)
4-
515
from trie.constants import (
616
BLANK_HASH,
717
BRANCH_TYPE,
@@ -30,12 +40,12 @@
3040

3141

3242
class BinaryTrie:
33-
def __init__(self, db, root_hash=BLANK_HASH):
43+
def __init__(self, db: Dict[bytes, bytes], root_hash: bytes = BLANK_HASH) -> None:
3444
self.db = db
3545
validate_is_bytes(root_hash)
3646
self.root_hash = root_hash
3747

38-
def get(self, key):
48+
def get(self, key: bytes) -> Optional[bytes]:
3949
"""
4050
Fetches the value with a given keypath from the given node.
4151
@@ -45,7 +55,7 @@ def get(self, key):
4555

4656
return self._get(self.root_hash, encode_to_bin(key))
4757

48-
def _get(self, node_hash, keypath):
58+
def _get(self, node_hash: bytes, keypath: bytes) -> Optional[bytes]:
4959
"""
5060
Note: keypath should be in binary array format, i.e., encoded by encode_to_bin()
5161
"""
@@ -76,7 +86,7 @@ def _get(self, node_hash, keypath):
7686
else:
7787
return self._get(right_child, keypath[1:])
7888

79-
def set(self, key, value):
89+
def set(self, key: bytes, value: bytes) -> None:
8090
"""
8191
Sets the value at the given keypath from the given node
8292
@@ -87,7 +97,11 @@ def set(self, key, value):
8797

8898
self.root_hash = self._set(self.root_hash, encode_to_bin(key), value)
8999

90-
def _set(self, node_hash, keypath, value, if_delete_subtrie=False):
100+
def _set(self,
101+
node_hash: bytes,
102+
keypath: bytes,
103+
value: bytes,
104+
if_delete_subtrie: bool = False) -> bytes:
91105
"""
92106
If if_delete_subtrie is set to True, what it will do is that it take in a
93107
keypath and traverse til the end of keypath, then delete the whole subtrie
@@ -155,14 +169,14 @@ def _set(self, node_hash, keypath, value, if_delete_subtrie=False):
155169

156170
def _set_kv_node(
157171
self,
158-
keypath,
159-
node_hash,
160-
node_type,
161-
left_child,
162-
right_child,
163-
value,
164-
if_delete_subtrie=False,
165-
):
172+
keypath: bytes,
173+
node_hash: bytes,
174+
node_type: int,
175+
left_child: bytes,
176+
right_child: bytes,
177+
value: bytes,
178+
if_delete_subtrie: bool = False,
179+
) -> bytes:
166180
# Keypath prefixes match
167181
if if_delete_subtrie:
168182
if len(keypath) < len(left_child) and keypath == left_child[: len(keypath)]:
@@ -257,13 +271,13 @@ def _set_kv_node(
257271

258272
def _set_branch_node(
259273
self,
260-
keypath,
261-
node_type,
262-
left_child,
263-
right_child,
264-
value,
265-
if_delete_subtrie=False,
266-
):
274+
keypath: bytes,
275+
node_type: int,
276+
left_child: bytes,
277+
right_child: bytes,
278+
value: bytes,
279+
if_delete_subtrie: bool = False,
280+
) -> bytes:
267281
# Which child node to update? Depends on first bit in keypath
268282
if keypath[:1] == BYTE_0:
269283
new_left_child = self._set(
@@ -303,20 +317,20 @@ def _set_branch_node(
303317
encode_branch_node(new_left_child, new_right_child)
304318
)
305319

306-
def exists(self, key):
320+
def exists(self, key: bytes) -> bool:
307321
validate_is_bytes(key)
308322

309323
return self.get(key) is not None
310324

311-
def delete(self, key):
325+
def delete(self, key: bytes) -> None:
312326
"""
313327
Equals to setting the value to None
314328
"""
315329
validate_is_bytes(key)
316330

317331
self.root_hash = self._set(self.root_hash, encode_to_bin(key), b"")
318332

319-
def delete_subtrie(self, key):
333+
def delete_subtrie(self, key: bytes) -> None:
320334
"""
321335
Given a key prefix, delete the whole subtrie that starts with the key prefix.
322336
@@ -337,19 +351,19 @@ def delete_subtrie(self, key):
337351
# Convenience
338352
#
339353
@property
340-
def root_node(self):
354+
def root_node(self) -> bytes:
341355
return self.db[self.root_hash]
342356

343357
@root_node.setter
344-
def root_node(self, node):
358+
def root_node(self, node: bytes) -> None:
345359
validate_is_bin_node(node)
346360

347361
self.root_hash = self._hash_and_save(node)
348362

349363
#
350364
# Utils
351365
#
352-
def _hash_and_save(self, node):
366+
def _hash_and_save(self, node: bytes) -> bytes:
353367
"""
354368
Saves a node into the database and returns its hash
355369
"""
@@ -362,14 +376,14 @@ def _hash_and_save(self, node):
362376
#
363377
# Dictionary API
364378
#
365-
def __getitem__(self, key):
379+
def __getitem__(self, key: bytes) -> Optional[bytes]:
366380
return self.get(key)
367381

368-
def __setitem__(self, key, value):
382+
def __setitem__(self, key: bytes, value: bytes) -> None:
369383
return self.set(key, value)
370384

371-
def __delitem__(self, key):
385+
def __delitem__(self, key: bytes) -> None:
372386
return self.delete(key)
373387

374-
def __contains__(self, key):
388+
def __contains__(self, key: bytes) -> bool:
375389
return self.exists(key)

trie/branches.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
from typing import (
2+
Dict,
3+
Iterator,
4+
Optional,
5+
Tuple,
6+
)
7+
18
from eth_hash.auto import (
29
keccak,
310
)
@@ -27,7 +34,7 @@
2734
)
2835

2936

30-
def check_if_branch_exist(db, root_hash, key_prefix):
37+
def check_if_branch_exist(db: Dict[bytes, bytes], root_hash: bytes, key_prefix: bytes) -> bool:
3138
"""
3239
Given a key prefix, return whether this prefix is
3340
the prefix of an existing key in the trie.
@@ -37,7 +44,7 @@ def check_if_branch_exist(db, root_hash, key_prefix):
3744
return _check_if_branch_exist(db, root_hash, encode_to_bin(key_prefix))
3845

3946

40-
def _check_if_branch_exist(db, node_hash, key_prefix):
47+
def _check_if_branch_exist(db: Dict[bytes, bytes], node_hash: bytes, key_prefix: bytes) -> bool:
4148
# Empty trie
4249
if node_hash == BLANK_HASH:
4350
return False
@@ -70,7 +77,7 @@ def _check_if_branch_exist(db, node_hash, key_prefix):
7077
raise Exception("Invariant: unreachable code path")
7178

7279

73-
def get_branch(db, root_hash, key):
80+
def get_branch(db: Dict[bytes, bytes], root_hash: bytes, key: bytes) -> Tuple[bytes, ...]:
7481
"""
7582
Get a long-format Merkle branch
7683
"""
@@ -79,7 +86,7 @@ def get_branch(db, root_hash, key):
7986
return tuple(_get_branch(db, root_hash, encode_to_bin(key)))
8087

8188

82-
def _get_branch(db, node_hash, keypath):
89+
def _get_branch(db: Dict[bytes, bytes], node_hash: bytes, keypath: bytes) -> Iterator[bytes]:
8390
if node_hash == BLANK_HASH:
8491
return
8592
node = db[node_hash]
@@ -110,7 +117,7 @@ def _get_branch(db, node_hash, keypath):
110117
raise Exception("Invariant: unreachable code path")
111118

112119

113-
def if_branch_valid(branch, root_hash, key, value):
120+
def if_branch_valid(branch: Tuple[bytes, ...], root_hash: bytes, key: bytes, value: Optional[bytes]) -> bool:
114121
# value being None means the key is not in the trie
115122
if value is not None:
116123
validate_is_bytes(key)
@@ -124,14 +131,14 @@ def if_branch_valid(branch, root_hash, key, value):
124131
return True
125132

126133

127-
def get_trie_nodes(db, node_hash):
134+
def get_trie_nodes(db: Dict[bytes, bytes], node_hash: bytes) -> Tuple[bytes, ...]:
128135
"""
129136
Get full trie of a given root node
130137
"""
131138
return tuple(_get_trie_nodes(db, node_hash))
132139

133140

134-
def _get_trie_nodes(db, node_hash):
141+
def _get_trie_nodes(db: Dict[bytes, bytes], node_hash: bytes) -> Iterator[bytes]:
135142
if node_hash in db:
136143
node = db[node_hash]
137144
else:
@@ -150,7 +157,7 @@ def _get_trie_nodes(db, node_hash):
150157
raise Exception("Invariant: unreachable code path")
151158

152159

153-
def get_witness_for_key_prefix(db, node_hash, key):
160+
def get_witness_for_key_prefix(db: Dict[bytes, bytes], node_hash: bytes, key: bytes) -> Tuple[bytes, ...]:
154161
"""
155162
Get all witness given a keypath prefix.
156163
Include
@@ -163,7 +170,7 @@ def get_witness_for_key_prefix(db, node_hash, key):
163170
return tuple(_get_witness_for_key_prefix(db, node_hash, encode_to_bin(key)))
164171

165172

166-
def _get_witness_for_key_prefix(db, node_hash, keypath):
173+
def _get_witness_for_key_prefix(db: Dict[bytes, bytes], node_hash: bytes, keypath: bytes) -> Iterator[bytes]:
167174
if not keypath:
168175
yield from get_trie_nodes(db, node_hash)
169176
if node_hash in db:

trie/constants.py

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
1-
BLANK_NODE = b""
1+
from typing import (
2+
Tuple,
3+
)
4+
5+
BLANK_NODE: bytes = b""
26
# keccak(b'')
3-
BLANK_HASH = b"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p" # noqa: E501
7+
BLANK_HASH: bytes = b"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\\x85\xa4p" # noqa: E501
48
# keccak(rlp.encode(b''))
5-
BLANK_NODE_HASH = b"V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n\x5bH\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!" # noqa: E501
9+
BLANK_NODE_HASH: bytes = b"V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n\x5bH\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!" # noqa: E501
610

711

8-
NIBBLE_TERMINATOR = 16
12+
NIBBLE_TERMINATOR: int = 16
913

10-
HP_FLAG_2 = 2
11-
HP_FLAG_0 = 0
14+
HP_FLAG_2: int = 2
15+
HP_FLAG_0: int = 0
1216

1317

14-
NODE_TYPE_BLANK = 0
15-
NODE_TYPE_LEAF = 1
16-
NODE_TYPE_EXTENSION = 2
17-
NODE_TYPE_BRANCH = 3
18+
NODE_TYPE_BLANK: int = 0
19+
NODE_TYPE_LEAF: int = 1
20+
NODE_TYPE_EXTENSION: int = 2
21+
NODE_TYPE_BRANCH: int = 3
1822

1923
# Constants for Binary Trie
20-
EXP = tuple(reversed(tuple(2**i for i in range(8))))
21-
22-
TWO_BITS = [bytes([0, 0]), bytes([0, 1]), bytes([1, 0]), bytes([1, 1])]
23-
PREFIX_00 = bytes([0, 0])
24-
PREFIX_100000 = bytes([1, 0, 0, 0, 0, 0])
25-
26-
KV_TYPE = 0
27-
BRANCH_TYPE = 1
28-
LEAF_TYPE = 2
29-
BINARY_TRIE_NODE_TYPES = (0, 1, 2)
30-
KV_TYPE_PREFIX = bytes([0])
31-
BRANCH_TYPE_PREFIX = bytes([1])
32-
LEAF_TYPE_PREFIX = bytes([2])
33-
34-
BYTE_1 = bytes([1])
35-
BYTE_0 = bytes([0])
24+
EXP: Tuple[int, ...] = tuple(reversed(tuple(2**i for i in range(8))))
25+
26+
TWO_BITS: Tuple[bytes, bytes, bytes, bytes] = (bytes([0, 0]), bytes([0, 1]), bytes([1, 0]), bytes([1, 1]))
27+
PREFIX_00: bytes = bytes([0, 0])
28+
PREFIX_100000: bytes = bytes([1, 0, 0, 0, 0, 0])
29+
30+
KV_TYPE: int = 0
31+
BRANCH_TYPE: int = 1
32+
LEAF_TYPE: int = 2
33+
BINARY_TRIE_NODE_TYPES: Tuple[int, int, int] = (0, 1, 2)
34+
KV_TYPE_PREFIX: bytes = bytes([0])
35+
BRANCH_TYPE_PREFIX: bytes = bytes([1])
36+
LEAF_TYPE_PREFIX: bytes = bytes([2])
37+
38+
BYTE_1: bytes = bytes([1])
39+
BYTE_0: bytes = bytes([0])

trie/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def __init__(
6565
requested_key: bytes,
6666
prefix: Nibbles = None,
6767
*args,
68-
):
68+
) -> None:
6969
if not isinstance(missing_node_hash, bytes):
7070
raise TypeError(
7171
"Missing node hash must be bytes, was: %r" % missing_node_hash

trie/hexary.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@
55
import functools
66
import itertools
77
from typing import (
8+
Any,
89
Callable,
10+
Dict,
11+
Iterator,
12+
List,
13+
Optional,
14+
Sequence,
15+
Set,
916
Tuple,
1017
TypeVar,
18+
Union,
1119
cast,
1220
)
1321

@@ -96,7 +104,7 @@ class HexaryTrie:
96104
BLANK_NODE_HASH = BLANK_NODE_HASH
97105
BLANK_NODE = BLANK_NODE
98106

99-
def __init__(self, db, root_hash=BLANK_NODE_HASH, prune=False, ref_count=None):
107+
def __init__(self, db: Dict, root_hash: bytes = BLANK_NODE_HASH, prune: bool = False, ref_count: Dict = None) -> None:
100108
"""
101109
Important note about Pruning:
102110
@@ -128,7 +136,7 @@ def __init__(self, db, root_hash=BLANK_NODE_HASH, prune=False, ref_count=None):
128136
)
129137
self._pending_prune_keys = None
130138

131-
def get(self, key):
139+
def get(self, key: bytes) -> bytes:
132140
validate_is_bytes(key)
133141

134142
trie_key = bytes_to_nibbles(key)

trie/py.typed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)