1
- import time
2
- from typing import Callable , Tuple , Optional
1
+ import datetime
2
+ from typing import (
3
+ Dict ,
4
+ Tuple ,
5
+ )
3
6
4
7
from eth_typing import (
5
- Address
8
+ Address ,
6
9
)
7
10
8
11
from eth .abc import BlockHeaderAPI
9
12
from eth .constants import (
10
- GENESIS_GAS_LIMIT ,
13
+ BLANK_ROOT_HASH ,
14
+ GENESIS_BLOCK_NUMBER ,
15
+ GENESIS_PARENT_HASH ,
11
16
GAS_LIMIT_EMA_DENOMINATOR ,
12
17
GAS_LIMIT_ADJUSTMENT_FACTOR ,
18
+ GAS_LIMIT_MAXIMUM ,
13
19
GAS_LIMIT_MINIMUM ,
14
20
GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR ,
15
21
GAS_LIMIT_USAGE_ADJUSTMENT_DENOMINATOR ,
22
+ ZERO_ADDRESS ,
16
23
)
17
- from eth .rlp .headers import (
18
- BlockHeader ,
24
+ from eth .typing import (
25
+ BlockNumber ,
26
+ HeaderParams ,
19
27
)
20
28
21
29
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 ]:
23
104
"""
24
105
Compute the boundaries for the block gas limit based on the parent block.
25
106
"""
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 )
29
110
return lower_bound , upper_bound
30
111
31
112
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 :
33
114
"""
34
115
A simple strategy for adjusting the gas limit.
35
116
@@ -38,21 +119,24 @@ def compute_gas_limit(parent_header: BlockHeaderAPI, gas_limit_floor: int) -> in
38
119
- decrease by 1/1024th of the gas limit from the previous block
39
120
- increase by 50% of the total gas used by the previous block
40
121
41
- If the value is less than the given `gas_limit_floor `:
122
+ If the value is less than the given `genesis_gas_limit `:
42
123
43
124
- increase the gas limit by 1/1024th of the gas limit from the previous block.
44
125
45
126
If the value is less than the GAS_LIMIT_MINIMUM:
46
127
47
128
- use the GAS_LIMIT_MINIMUM as the new gas limit.
48
129
"""
49
- if gas_limit_floor < GAS_LIMIT_MINIMUM :
130
+ if genesis_gas_limit < GAS_LIMIT_MINIMUM :
50
131
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 "
53
134
f"{ GAS_LIMIT_MINIMUM } "
54
135
)
55
136
137
+ if parent_header is None :
138
+ return genesis_gas_limit
139
+
56
140
decay = parent_header .gas_limit // GAS_LIMIT_EMA_DENOMINATOR
57
141
58
142
if parent_header .gas_used :
@@ -73,40 +157,7 @@ def compute_gas_limit(parent_header: BlockHeaderAPI, gas_limit_floor: int) -> in
73
157
74
158
if gas_limit < GAS_LIMIT_MINIMUM :
75
159
return GAS_LIMIT_MINIMUM
76
- elif gas_limit < gas_limit_floor :
160
+ elif gas_limit < genesis_gas_limit :
77
161
return parent_header .gas_limit + decay
78
162
else :
79
163
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