1- import time
2- from typing import Callable , Tuple , Optional
1+ import datetime
2+ from typing import (
3+ Dict ,
4+ Tuple ,
5+ )
36
47from eth_typing import (
5- Address
8+ Address ,
69)
710
811from eth .abc import BlockHeaderAPI
912from eth .constants import (
10- GENESIS_GAS_LIMIT ,
13+ BLANK_ROOT_HASH ,
14+ GENESIS_BLOCK_NUMBER ,
15+ GENESIS_PARENT_HASH ,
1116 GAS_LIMIT_EMA_DENOMINATOR ,
1217 GAS_LIMIT_ADJUSTMENT_FACTOR ,
18+ GAS_LIMIT_MAXIMUM ,
1319 GAS_LIMIT_MINIMUM ,
1420 GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR ,
1521 GAS_LIMIT_USAGE_ADJUSTMENT_DENOMINATOR ,
22+ ZERO_ADDRESS ,
1623)
17- from eth .rlp .headers import (
18- BlockHeader ,
24+ from eth .typing import (
25+ BlockNumber ,
26+ HeaderParams ,
1927)
2028
2129
22- def compute_gas_limit_bounds (parent : BlockHeaderAPI ) -> Tuple [int , int ]:
30+ def eth_now () -> int :
31+ """
32+ The timestamp is in UTC.
33+ """
34+ return int (datetime .datetime .utcnow ().timestamp ())
35+
36+
37+ def new_timestamp_from_parent (parent : BlockHeaderAPI ) -> int :
38+ """
39+ Generate a timestamp to use on a new header.
40+
41+ Generally, attempt to use the current time. If timestamp is too old (equal
42+ or less than parent), return `parent.timestamp + 1`. If parent is None,
43+ then consider this a genesis block.
44+ """
45+ if parent is None :
46+ return eth_now ()
47+ else :
48+ # header timestamps must increment
49+ return max (
50+ parent .timestamp + 1 ,
51+ eth_now (),
52+ )
53+
54+
55+ def fill_header_params_from_parent (
56+ parent : BlockHeaderAPI ,
57+ gas_limit : int ,
58+ difficulty : int ,
59+ timestamp : int ,
60+ coinbase : Address = ZERO_ADDRESS ,
61+ nonce : bytes = None ,
62+ extra_data : bytes = None ,
63+ transaction_root : bytes = None ,
64+ state_root : bytes = None ,
65+ mix_hash : bytes = None ,
66+ receipt_root : bytes = None ) -> Dict [str , HeaderParams ]:
67+
68+ if parent is None :
69+ parent_hash = GENESIS_PARENT_HASH
70+ block_number = GENESIS_BLOCK_NUMBER
71+ if state_root is None :
72+ state_root = BLANK_ROOT_HASH
73+ else :
74+ parent_hash = parent .hash
75+ block_number = BlockNumber (parent .block_number + 1 )
76+
77+ if state_root is None :
78+ state_root = parent .state_root
79+
80+ header_kwargs : Dict [str , HeaderParams ] = {
81+ 'parent_hash' : parent_hash ,
82+ 'coinbase' : coinbase ,
83+ 'state_root' : state_root ,
84+ 'gas_limit' : gas_limit ,
85+ 'difficulty' : difficulty ,
86+ 'block_number' : block_number ,
87+ 'timestamp' : timestamp ,
88+ }
89+ if nonce is not None :
90+ header_kwargs ['nonce' ] = nonce
91+ if extra_data is not None :
92+ header_kwargs ['extra_data' ] = extra_data
93+ if transaction_root is not None :
94+ header_kwargs ['transaction_root' ] = transaction_root
95+ if receipt_root is not None :
96+ header_kwargs ['receipt_root' ] = receipt_root
97+ if mix_hash is not None :
98+ header_kwargs ['mix_hash' ] = mix_hash
99+
100+ return header_kwargs
101+
102+
103+ def compute_gas_limit_bounds (previous_limit : int ) -> Tuple [int , int ]:
23104 """
24105 Compute the boundaries for the block gas limit based on the parent block.
25106 """
26- boundary_range = parent . gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
27- upper_bound = parent . gas_limit + boundary_range
28- lower_bound = max (GAS_LIMIT_MINIMUM , parent . gas_limit - boundary_range )
107+ boundary_range = previous_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
108+ upper_bound = min ( GAS_LIMIT_MAXIMUM , previous_limit + boundary_range )
109+ lower_bound = max (GAS_LIMIT_MINIMUM , previous_limit - boundary_range )
29110 return lower_bound , upper_bound
30111
31112
32- def compute_gas_limit (parent_header : BlockHeaderAPI , gas_limit_floor : int ) -> int :
113+ def compute_gas_limit (parent_header : BlockHeaderAPI , genesis_gas_limit : int ) -> int :
33114 """
34115 A simple strategy for adjusting the gas limit.
35116
@@ -38,21 +119,24 @@ def compute_gas_limit(parent_header: BlockHeaderAPI, gas_limit_floor: int) -> in
38119 - decrease by 1/1024th of the gas limit from the previous block
39120 - increase by 50% of the total gas used by the previous block
40121
41- If the value is less than the given `gas_limit_floor `:
122+ If the value is less than the given `genesis_gas_limit `:
42123
43124 - increase the gas limit by 1/1024th of the gas limit from the previous block.
44125
45126 If the value is less than the GAS_LIMIT_MINIMUM:
46127
47128 - use the GAS_LIMIT_MINIMUM as the new gas limit.
48129 """
49- if gas_limit_floor < GAS_LIMIT_MINIMUM :
130+ if genesis_gas_limit < GAS_LIMIT_MINIMUM :
50131 raise ValueError (
51- "The `gas_limit_floor ` value must be greater than the "
52- f"GAS_LIMIT_MINIMUM. Got { gas_limit_floor } . Must be greater than "
132+ "The `genesis_gas_limit ` value must be greater than the "
133+ f"GAS_LIMIT_MINIMUM. Got { genesis_gas_limit } . Must be greater than "
53134 f"{ GAS_LIMIT_MINIMUM } "
54135 )
55136
137+ if parent_header is None :
138+ return genesis_gas_limit
139+
56140 decay = parent_header .gas_limit // GAS_LIMIT_EMA_DENOMINATOR
57141
58142 if parent_header .gas_used :
@@ -73,40 +157,7 @@ def compute_gas_limit(parent_header: BlockHeaderAPI, gas_limit_floor: int) -> in
73157
74158 if gas_limit < GAS_LIMIT_MINIMUM :
75159 return GAS_LIMIT_MINIMUM
76- elif gas_limit < gas_limit_floor :
160+ elif gas_limit < genesis_gas_limit :
77161 return parent_header .gas_limit + decay
78162 else :
79163 return gas_limit
80-
81-
82- def generate_header_from_parent_header (
83- compute_difficulty_fn : Callable [[BlockHeaderAPI , int ], int ],
84- parent_header : BlockHeaderAPI ,
85- coinbase : Address ,
86- timestamp : Optional [int ] = None ,
87- extra_data : bytes = b'' ) -> BlockHeader :
88- """
89- Generate BlockHeader from state_root and parent_header
90- """
91- if timestamp is None :
92- timestamp = max (int (time .time ()), parent_header .timestamp + 1 )
93- elif timestamp <= parent_header .timestamp :
94- raise ValueError (
95- f"header.timestamp ({ timestamp } ) should be higher than"
96- f"parent_header.timestamp ({ parent_header .timestamp } )"
97- )
98- header = BlockHeader (
99- difficulty = compute_difficulty_fn (parent_header , timestamp ),
100- block_number = (parent_header .block_number + 1 ),
101- gas_limit = compute_gas_limit (
102- parent_header ,
103- gas_limit_floor = GENESIS_GAS_LIMIT ,
104- ),
105- timestamp = timestamp ,
106- parent_hash = parent_header .hash ,
107- state_root = parent_header .state_root ,
108- coinbase = coinbase ,
109- extra_data = extra_data ,
110- )
111-
112- return header
0 commit comments