22import rlp
33
44from eth_utils import decode_hex
5+ from eth_utils .toolz import sliding_window
56
67from eth import constants
78from 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+ )
914from eth .chains .ropsten import ROPSTEN_GENESIS_HEADER
15+ from eth .consensus .noproof import NoProofConsensus
1016from 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
2959def 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