Skip to content

Commit d479919

Browse files
committed
Add test to validate uncles across chain VMs
Plus, fixed first bug: must double the header's gas limit at the VM boundary.
1 parent 71f0552 commit d479919

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

eth/vm/forks/london/headers.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from .blocks import LondonBlockHeader
2929
from .constants import (
3030
BASE_FEE_MAX_CHANGE_DENOMINATOR,
31+
ELASTICITY_MULTIPLIER,
3132
INITIAL_BASE_FEE,
3233
)
3334

@@ -72,12 +73,17 @@ def create_header_from_parent(difficulty_fn: Callable[[BlockHeaderAPI, int], int
7273
parent_header: Optional[BlockHeaderAPI],
7374
**header_params: Any) -> BlockHeaderAPI:
7475

75-
# frontier
7676
if 'gas_limit' not in header_params:
77-
header_params['gas_limit'] = compute_gas_limit(
78-
parent_header,
79-
genesis_gas_limit=GENESIS_GAS_LIMIT,
80-
)
77+
if parent_header.base_fee_per_gas is None:
78+
# If the previous block was not a London block,
79+
# double the gas limit, so the new target is the old gas limit
80+
header_params['gas_limit'] = parent_header.gas_limit * ELASTICITY_MULTIPLIER
81+
else:
82+
# frontier rules
83+
header_params['gas_limit'] = compute_gas_limit(
84+
parent_header,
85+
genesis_gas_limit=GENESIS_GAS_LIMIT,
86+
)
8187

8288
# byzantium
8389
if 'timestamp' not in header_params:

tests/core/chain-object/test_chain.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
import rlp
33

44
from eth_utils import decode_hex
5+
from eth_utils.toolz import sliding_window
56

67
from eth import constants
78
from eth.abc import MiningChainAPI
8-
from eth.chains.mainnet import MAINNET_GENESIS_HEADER
9+
from eth.chains.base import MiningChain
10+
from eth.chains.mainnet import (
11+
MAINNET_GENESIS_HEADER,
12+
MAINNET_VMS,
13+
)
914
from eth.chains.ropsten import ROPSTEN_GENESIS_HEADER
15+
from eth.consensus.noproof import NoProofConsensus
1016
from eth.exceptions import (
1117
TransactionNotFound,
1218
)
@@ -25,6 +31,30 @@ def chain(chain_without_block_validation):
2531
return chain_without_block_validation
2632

2733

34+
VM_PAIRS = sliding_window(2, MAINNET_VMS)
35+
36+
37+
@pytest.fixture(params=VM_PAIRS)
38+
def vm_crossover_chain(request, base_db, genesis_state):
39+
start_vm, end_vm = request.param
40+
klass = MiningChain.configure(
41+
__name__='CrossoverTestChain',
42+
vm_configuration=(
43+
(
44+
constants.GENESIS_BLOCK_NUMBER,
45+
start_vm.configure(consensus_class=NoProofConsensus),
46+
),
47+
# Can mine one block of the first VM, then the next block with be the next VM
48+
(
49+
constants.GENESIS_BLOCK_NUMBER + 2,
50+
end_vm.configure(consensus_class=NoProofConsensus),
51+
),
52+
),
53+
chain_id=1337,
54+
)
55+
return klass.from_genesis(base_db, dict(difficulty=1), genesis_state)
56+
57+
2858
@pytest.fixture
2959
def valid_chain(chain_with_block_validation):
3060
return chain_with_block_validation
@@ -200,3 +230,37 @@ def test_get_transaction_receipt(chain, tx):
200230
assert chain.get_canonical_transaction_index(tx.hash) == (1, 0)
201231
assert chain.get_transaction_receipt_by_index(1, 0) == expected_receipt
202232
assert chain.get_transaction_receipt(tx.hash) == expected_receipt
233+
234+
235+
def _mine_result_to_header(mine_all_result):
236+
block_import_result, _, _ = mine_all_result
237+
return block_import_result.imported_block.header
238+
239+
240+
def test_uncles_across_VMs(vm_crossover_chain):
241+
chain = vm_crossover_chain
242+
243+
genesis = chain.get_canonical_block_header_by_number(0)
244+
245+
# Mine in 1st VM
246+
uncle_header1 = chain.mine_block(extra_data=b'uncle1').header
247+
canon_header1 = _mine_result_to_header(
248+
chain.mine_all([], parent_header=genesis)
249+
)
250+
251+
# Mine in 2nd VM
252+
uncle_header2 = chain.mine_block(extra_data=b'uncle2').header
253+
canon_header2 = _mine_result_to_header(
254+
chain.mine_all([], parent_header=canon_header1)
255+
)
256+
257+
# Mine block with uncles from both VMs
258+
canon_block3 = chain.mine_block(uncles=[uncle_header1, uncle_header2])
259+
260+
assert canon_header2.hash == canon_block3.header.parent_hash
261+
262+
assert canon_block3.uncles == (uncle_header1, uncle_header2)
263+
264+
deserialized_block3 = chain.get_canonical_block_by_number(3)
265+
266+
assert deserialized_block3.uncles == (uncle_header1, uncle_header2)

0 commit comments

Comments
 (0)