File tree Expand file tree Collapse file tree 6 files changed +78
-16
lines changed
tests/core/generator-utils Expand file tree Collapse file tree 6 files changed +78
-16
lines changed Original file line number Diff line number Diff line change
1
+ import itertools
2
+ from typing import ( # noqa: F401
3
+ Generic ,
4
+ Iterable ,
5
+ Iterator ,
6
+ List ,
7
+ TypeVar ,
8
+ )
9
+
10
+
11
+ TItem = TypeVar ('TItem' )
12
+
13
+
14
+ class CachedIterable (Generic [TItem ], Iterable [TItem ]):
15
+ def __init__ (self , iterable : Iterable [TItem ]) -> None :
16
+ self ._cached_results = [] # type: List[TItem]
17
+ self ._iterator = iter (iterable )
18
+
19
+ def __iter__ (self ) -> Iterator [TItem ]:
20
+ return itertools .chain (self ._cached_results , self ._cache_and_yield ())
21
+
22
+ def _cache_and_yield (self ) -> Iterator [TItem ]:
23
+ for item in self ._iterator :
24
+ self ._cached_results .append (item )
25
+ yield item
Original file line number Diff line number Diff line change 1
1
import time
2
2
from typing import (
3
+ Iterable ,
3
4
Optional ,
4
- Tuple ,
5
5
Union ,
6
6
overload ,
7
7
)
@@ -203,7 +203,7 @@ def from_parent(cls,
203
203
return header
204
204
205
205
def create_execution_context (
206
- self , prev_hashes : Tuple [Hash32 , ... ]) -> ExecutionContext :
206
+ self , prev_hashes : Iterable [Hash32 ]) -> ExecutionContext :
207
207
208
208
return ExecutionContext (
209
209
coinbase = self .coinbase ,
Original file line number Diff line number Diff line change 4
4
abstractmethod ,
5
5
)
6
6
import contextlib
7
- import functools
7
+ import itertools
8
8
import logging
9
9
from typing import (
10
10
Any ,
28
28
)
29
29
30
30
from eth_utils import (
31
- to_tuple ,
32
31
ValidationError ,
33
32
)
34
33
@@ -258,7 +257,6 @@ def get_nephew_reward(cls) -> int:
258
257
259
258
@classmethod
260
259
@abstractmethod
261
- @to_tuple
262
260
def get_prev_hashes (cls ,
263
261
last_block_hash : Hash32 ,
264
262
chaindb : BaseChainDB ) -> Optional [Iterable [Hash32 ]]:
@@ -691,8 +689,6 @@ def get_block_class(cls) -> Type[BaseBlock]:
691
689
return cls .block_class
692
690
693
691
@classmethod
694
- @functools .lru_cache (maxsize = 32 )
695
- @to_tuple
696
692
def get_prev_hashes (cls ,
697
693
last_block_hash : Hash32 ,
698
694
chaindb : BaseChainDB ) -> Optional [Iterable [Hash32 ]]:
@@ -709,7 +705,7 @@ def get_prev_hashes(cls,
709
705
break
710
706
711
707
@property
712
- def previous_hashes (self ) -> Optional [Tuple [Hash32 , ... ]]:
708
+ def previous_hashes (self ) -> Optional [Iterable [Hash32 ]]:
713
709
"""
714
710
Convenience API for accessing the previous 255 block hashes.
715
711
"""
@@ -919,7 +915,7 @@ def get_state_class(cls) -> Type[BaseState]:
919
915
def state_in_temp_block (self ) -> Iterator [BaseState ]:
920
916
header = self .block .header
921
917
temp_block = self .generate_block_from_parent_header_and_coinbase (header , header .coinbase )
922
- prev_hashes = ( header .hash , ) + self .previous_hashes
918
+ prev_hashes = itertools . chain (( header .hash , ), self .previous_hashes )
923
919
924
920
state = self .get_state_class ()(
925
921
db = self .chaindb .db ,
Original file line number Diff line number Diff line change 1
- from typing import Tuple
1
+ from typing import (
2
+ Iterable ,
3
+ )
2
4
3
5
from eth_typing import (
4
6
Address ,
5
7
Hash32 ,
6
8
)
7
9
10
+ from eth ._utils .generator import CachedIterable
11
+
8
12
9
13
class ExecutionContext :
10
14
_coinbase = None
@@ -22,13 +26,13 @@ def __init__(
22
26
block_number : int ,
23
27
difficulty : int ,
24
28
gas_limit : int ,
25
- prev_hashes : Tuple [Hash32 , ... ]) -> None :
29
+ prev_hashes : Iterable [Hash32 ]) -> None :
26
30
self ._coinbase = coinbase
27
31
self ._timestamp = timestamp
28
32
self ._block_number = block_number
29
33
self ._difficulty = difficulty
30
34
self ._gas_limit = gas_limit
31
- self ._prev_hashes = prev_hashes
35
+ self ._prev_hashes = CachedIterable ( prev_hashes )
32
36
33
37
@property
34
38
def coinbase (self ) -> Address :
@@ -51,5 +55,5 @@ def gas_limit(self) -> int:
51
55
return self ._gas_limit
52
56
53
57
@property
54
- def prev_hashes (self ) -> Tuple [Hash32 , ... ]:
58
+ def prev_hashes (self ) -> Iterable [Hash32 ]:
55
59
return self ._prev_hashes
Original file line number Diff line number Diff line change 19
19
Address ,
20
20
Hash32 ,
21
21
)
22
+ from eth_utils .toolz import nth
22
23
23
24
from eth .constants import (
24
25
BLANK_ROOT_HASH ,
@@ -201,12 +202,16 @@ def get_ancestor_hash(self, block_number: int) -> Hash32:
201
202
is_ancestor_depth_out_of_range = (
202
203
ancestor_depth >= MAX_PREV_HEADER_DEPTH or
203
204
ancestor_depth < 0 or
204
- ancestor_depth >= len ( self . execution_context . prev_hashes )
205
+ block_number < 0
205
206
)
206
207
if is_ancestor_depth_out_of_range :
207
208
return Hash32 (b'' )
208
- ancestor_hash = self .execution_context .prev_hashes [ancestor_depth ]
209
- return ancestor_hash
209
+
210
+ try :
211
+ return nth (ancestor_depth , self .execution_context .prev_hashes )
212
+ except StopIteration :
213
+ # Ancestor with specified depth not present
214
+ return Hash32 (b'' )
210
215
211
216
#
212
217
# Computation
Original file line number Diff line number Diff line change
1
+ from eth ._utils .generator import CachedIterable
2
+
3
+ from eth_utils .toolz import (
4
+ first ,
5
+ nth ,
6
+ )
7
+ import itertools
8
+
9
+
10
+ def test_cached_generator ():
11
+ use_once = itertools .count ()
12
+ repeated_use = CachedIterable (use_once )
13
+
14
+ for find_val in [1 , 0 , 10 , 5 ]:
15
+ assert find_val == nth (find_val , repeated_use )
16
+
17
+
18
+ def test_laziness ():
19
+ def crash_after_first_val ():
20
+ yield 1
21
+ raise Exception ("oops, iterated past first value" )
22
+
23
+ repeated_use = CachedIterable (crash_after_first_val ())
24
+ assert first (repeated_use ) == 1
25
+ assert first (repeated_use ) == 1
26
+
27
+
28
+ def test_cached_generator_iterable ():
29
+ input_vals = [2 ]
30
+ repeated_use = CachedIterable (input_vals )
31
+ assert list (repeated_use ) == input_vals
32
+ assert list (repeated_use ) == input_vals
You can’t perform that action at this time.
0 commit comments