This repository was archived by the owner on Sep 8, 2025. It is now read-only.
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 11import time
22from typing import (
3+ Iterable ,
34 Optional ,
4- Tuple ,
55 Union ,
66 overload ,
77)
@@ -203,7 +203,7 @@ def from_parent(cls,
203203 return header
204204
205205 def create_execution_context (
206- self , prev_hashes : Tuple [Hash32 , ... ]) -> ExecutionContext :
206+ self , prev_hashes : Iterable [Hash32 ]) -> ExecutionContext :
207207
208208 return ExecutionContext (
209209 coinbase = self .coinbase ,
Original file line number Diff line number Diff line change 44 abstractmethod ,
55)
66import contextlib
7- import functools
7+ import itertools
88import logging
99from typing import (
1010 Any ,
2828)
2929
3030from eth_utils import (
31- to_tuple ,
3231 ValidationError ,
3332)
3433
@@ -258,7 +257,6 @@ def get_nephew_reward(cls) -> int:
258257
259258 @classmethod
260259 @abstractmethod
261- @to_tuple
262260 def get_prev_hashes (cls ,
263261 last_block_hash : Hash32 ,
264262 chaindb : BaseChainDB ) -> Optional [Iterable [Hash32 ]]:
@@ -691,8 +689,6 @@ def get_block_class(cls) -> Type[BaseBlock]:
691689 return cls .block_class
692690
693691 @classmethod
694- @functools .lru_cache (maxsize = 32 )
695- @to_tuple
696692 def get_prev_hashes (cls ,
697693 last_block_hash : Hash32 ,
698694 chaindb : BaseChainDB ) -> Optional [Iterable [Hash32 ]]:
@@ -709,7 +705,7 @@ def get_prev_hashes(cls,
709705 break
710706
711707 @property
712- def previous_hashes (self ) -> Optional [Tuple [Hash32 , ... ]]:
708+ def previous_hashes (self ) -> Optional [Iterable [Hash32 ]]:
713709 """
714710 Convenience API for accessing the previous 255 block hashes.
715711 """
@@ -919,7 +915,7 @@ def get_state_class(cls) -> Type[BaseState]:
919915 def state_in_temp_block (self ) -> Iterator [BaseState ]:
920916 header = self .block .header
921917 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 )
923919
924920 state = self .get_state_class ()(
925921 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+ )
24
35from eth_typing import (
46 Address ,
57 Hash32 ,
68)
79
10+ from eth ._utils .generator import CachedIterable
11+
812
913class ExecutionContext :
1014 _coinbase = None
@@ -22,13 +26,13 @@ def __init__(
2226 block_number : int ,
2327 difficulty : int ,
2428 gas_limit : int ,
25- prev_hashes : Tuple [Hash32 , ... ]) -> None :
29+ prev_hashes : Iterable [Hash32 ]) -> None :
2630 self ._coinbase = coinbase
2731 self ._timestamp = timestamp
2832 self ._block_number = block_number
2933 self ._difficulty = difficulty
3034 self ._gas_limit = gas_limit
31- self ._prev_hashes = prev_hashes
35+ self ._prev_hashes = CachedIterable ( prev_hashes )
3236
3337 @property
3438 def coinbase (self ) -> Address :
@@ -51,5 +55,5 @@ def gas_limit(self) -> int:
5155 return self ._gas_limit
5256
5357 @property
54- def prev_hashes (self ) -> Tuple [Hash32 , ... ]:
58+ def prev_hashes (self ) -> Iterable [Hash32 ]:
5559 return self ._prev_hashes
Original file line number Diff line number Diff line change 1919 Address ,
2020 Hash32 ,
2121)
22+ from eth_utils .toolz import nth
2223
2324from eth .constants import (
2425 BLANK_ROOT_HASH ,
@@ -201,12 +202,16 @@ def get_ancestor_hash(self, block_number: int) -> Hash32:
201202 is_ancestor_depth_out_of_range = (
202203 ancestor_depth >= MAX_PREV_HEADER_DEPTH or
203204 ancestor_depth < 0 or
204- ancestor_depth >= len ( self . execution_context . prev_hashes )
205+ block_number < 0
205206 )
206207 if is_ancestor_depth_out_of_range :
207208 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'' )
210215
211216 #
212217 # 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