Skip to content

Commit 09c04be

Browse files
authored
Merge pull request #2013 from carver/eip-1559
Add Dynamic fee transactions, EIP-1559 for London
2 parents 1af151a + 295cc29 commit 09c04be

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+2120
-523
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ clean-pyc:
2323
find . -name '__pycache__' -exec rm -rf {} +
2424

2525
lint:
26-
tox -epy3{6,5}-lint
26+
tox -epy38-lint
2727

2828
test:
2929
py.test --tb native tests

docs/cookbook/index.rst

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,7 @@ state.
7979
... }
8080

8181
>>> GENESIS_PARAMS = {
82-
... 'parent_hash': constants.GENESIS_PARENT_HASH,
83-
... 'uncles_hash': constants.EMPTY_UNCLE_HASH,
84-
... 'coinbase': constants.ZERO_ADDRESS,
85-
... 'transaction_root': constants.BLANK_ROOT_HASH,
86-
... 'receipt_root': constants.BLANK_ROOT_HASH,
8782
... 'difficulty': constants.GENESIS_DIFFICULTY,
88-
... 'block_number': constants.GENESIS_BLOCK_NUMBER,
89-
... 'gas_limit': constants.GENESIS_GAS_LIMIT,
90-
... 'extra_data': constants.GENESIS_EXTRA_DATA,
91-
... 'nonce': constants.GENESIS_NONCE
9283
... }
9384

9485
>>> chain = MainnetChain.from_genesis(AtomicDB(), GENESIS_PARAMS, GENESIS_STATE)

docs/guides/building_an_app_that_uses_pyevm.rst

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,7 @@ Next, we'll create a new directory ``app`` and create a file ``main.py`` inside.
8383
>>> DEFAULT_INITIAL_BALANCE = to_wei(10000, 'ether')
8484

8585
>>> GENESIS_PARAMS = {
86-
... 'parent_hash': constants.GENESIS_PARENT_HASH,
87-
... 'uncles_hash': constants.EMPTY_UNCLE_HASH,
88-
... 'coinbase': constants.ZERO_ADDRESS,
89-
... 'transaction_root': constants.BLANK_ROOT_HASH,
90-
... 'receipt_root': constants.BLANK_ROOT_HASH,
9186
... 'difficulty': constants.GENESIS_DIFFICULTY,
92-
... 'block_number': constants.GENESIS_BLOCK_NUMBER,
93-
... 'gas_limit': constants.GENESIS_GAS_LIMIT,
94-
... 'extra_data': constants.GENESIS_EXTRA_DATA,
95-
... 'nonce': constants.GENESIS_NONCE
9687
... }
9788

9889
>>> GENESIS_STATE = {

docs/guides/understanding_the_mining_process.rst

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,9 @@ Let's start off by defining the ``GENESIS_PARAMS``.
146146
from eth import constants
147147

148148
GENESIS_PARAMS = {
149-
'parent_hash': constants.GENESIS_PARENT_HASH,
150-
'uncles_hash': constants.EMPTY_UNCLE_HASH,
151-
'coinbase': constants.ZERO_ADDRESS,
152-
'transaction_root': constants.BLANK_ROOT_HASH,
153-
'receipt_root': constants.BLANK_ROOT_HASH,
154149
'difficulty': 1,
155-
'block_number': constants.GENESIS_BLOCK_NUMBER,
156150
'gas_limit': 3141592,
157151
'timestamp': 1514764800,
158-
'extra_data': constants.GENESIS_EXTRA_DATA,
159-
'nonce': constants.GENESIS_NONCE
160152
}
161153

162154
Next, we'll create the chain itself using the defined ``GENESIS_PARAMS`` and the latest
@@ -327,17 +319,11 @@ zero value transfer transaction.
327319

328320

329321
>>> GENESIS_PARAMS = {
330-
... 'parent_hash': constants.GENESIS_PARENT_HASH,
331-
... 'uncles_hash': constants.EMPTY_UNCLE_HASH,
332-
... 'coinbase': constants.ZERO_ADDRESS,
333-
... 'transaction_root': constants.BLANK_ROOT_HASH,
334-
... 'receipt_root': constants.BLANK_ROOT_HASH,
335322
... 'difficulty': 1,
336-
... 'block_number': constants.GENESIS_BLOCK_NUMBER,
337323
... 'gas_limit': 3141592,
324+
... # We set the timestamp, just to make this documented example reproducible.
325+
... # In common usage, we remove the field to let py-evm choose a reasonable default.
338326
... 'timestamp': 1514764800,
339-
... 'extra_data': constants.GENESIS_EXTRA_DATA,
340-
... 'nonce': constants.GENESIS_NONCE
341327
... }
342328

343329
>>> SENDER_PRIVATE_KEY = keys.PrivateKey(
@@ -355,6 +341,7 @@ zero value transfer transaction.
355341
... ))
356342

357343
>>> chain = klass.from_genesis(AtomicDB(), GENESIS_PARAMS)
344+
>>> genesis = chain.get_canonical_block_header_by_number(0)
358345
>>> vm = chain.get_vm()
359346

360347
>>> nonce = vm.state.get_nonce(SENDER)
@@ -372,6 +359,12 @@ zero value transfer transaction.
372359

373360
>>> chain.apply_transaction(signed_tx)
374361
(<ByzantiumBlock(#Block #1...)
362+
363+
>>> # Normally, we can let the timestamp be chosen automatically, but
364+
>>> # for the sake of reproducing exactly the same block every time,
365+
>>> # we will set it manually here:
366+
>>> chain.set_header_timestamp(genesis.timestamp + 1)
367+
375368
>>> # We have to finalize the block first in order to be able read the
376369
>>> # attributes that are important for the PoW algorithm
377370
>>> block_result = chain.get_vm().finalize_block(chain.get_block())

eth/_utils/headers.py

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,116 @@
1-
import time
2-
from typing import Callable, Tuple, Optional
1+
import datetime
2+
from typing import (
3+
Dict,
4+
Tuple,
5+
)
36

47
from eth_typing import (
5-
Address
8+
Address,
69
)
710

811
from eth.abc import BlockHeaderAPI
912
from 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

Comments
 (0)