1
1
"""Ethereum blockchain test spec definition and filler."""
2
2
3
3
from pprint import pprint
4
- from typing import Any , Callable , ClassVar , Dict , Generator , List , Optional , Sequence , Tuple , Type
4
+ from typing import Any , Callable , ClassVar , Dict , Generator , List , Sequence , Tuple , Type
5
5
6
6
import pytest
7
7
from pydantic import ConfigDict , Field , field_validator
@@ -404,6 +404,8 @@ class BlockchainTest(BaseTest):
404
404
post : Alloc
405
405
blocks : List [Block ]
406
406
genesis_environment : Environment = Field (default_factory = Environment )
407
+ # If set to True, generate a BlockchainEngineSyncFixture to
408
+ # verify syncing between clients.
407
409
verify_sync : bool = False
408
410
chain_id : int = 1
409
411
exclude_full_post_state_in_output : bool = False
@@ -429,7 +431,7 @@ class BlockchainTest(BaseTest):
429
431
supported_markers : ClassVar [Dict [str , str ]] = {
430
432
"blockchain_test_engine_only" : "Only generate a blockchain test engine fixture" ,
431
433
"blockchain_test_only" : "Only generate a blockchain test fixture" ,
432
- "blockchain_engine_sync_test " : "Generate a blockchain engine sync test fixture" ,
434
+ "blockchain_test_sync_only " : "Only generate a blockchain test sync fixture" ,
433
435
}
434
436
435
437
@classmethod
@@ -446,12 +448,11 @@ def discard_fixture_format_by_marks(
446
448
return fixture_format != BlockchainFixture
447
449
if "blockchain_test_engine_only" in marker_names :
448
450
return fixture_format != BlockchainEngineFixture
449
- if "blockchain_engine_sync_test" in marker_names :
450
- # Only generate sync fixture when marker is present
451
- return fixture_format != BlockchainEngineSyncFixture
452
- else :
453
- # When sync marker is NOT present, exclude sync fixture
454
- return fixture_format == BlockchainEngineSyncFixture
451
+ # Note: Don't check for ``blockchain_test_sync_only`` here because the marker
452
+ # is added dynamically for tests with ``verify_sync=True``. The ``generate()``
453
+ # method handles skipping sync fixtures when ``verify_sync=False``.
454
+
455
+ return False
455
456
456
457
def get_genesis_environment (self , fork : Fork ) -> Environment :
457
458
"""Get the genesis environment for pre-allocation groups."""
@@ -764,27 +765,11 @@ def make_hive_fixture(
764
765
765
766
self .verify_post_state (t8n , t8n_state = alloc )
766
767
767
- sync_payload : Optional [FixtureEngineNewPayload ] = None
768
- # Only include sync_payload for BlockchainEngineSyncFixture
769
- if fixture_format == BlockchainEngineSyncFixture :
770
- # Test is marked for syncing verification.
771
- # Most clients require the header to start the sync process, so we create an empty
772
- # block on top of the last block of the test to send it as new payload and trigger
773
- # the sync process.
774
- sync_built_block = self .generate_block_data (
775
- t8n = t8n ,
776
- fork = fork ,
777
- block = Block (),
778
- previous_env = env ,
779
- previous_alloc = alloc ,
780
- last_block = False ,
781
- )
782
- sync_payload = sync_built_block .get_fixture_engine_new_payload ()
783
-
784
- # Create base fixture data
768
+ # Create base fixture data, common to all fixture formats
785
769
fixture_data = {
786
770
"fork" : fork ,
787
771
"genesis" : genesis .header ,
772
+ "payloads" : fixture_payloads ,
788
773
"last_block_hash" : head_hash ,
789
774
"post_state_hash" : alloc .state_root ()
790
775
if self .exclude_full_post_state_in_output
@@ -802,19 +787,30 @@ def make_hive_fixture(
802
787
# and prepare for state diff optimization
803
788
fixture_data .update (
804
789
{
805
- "payloads" : fixture_payloads ,
806
- "sync_payload" : sync_payload ,
807
790
"post_state" : alloc if not self .exclude_full_post_state_in_output else None ,
808
791
"pre_hash" : "" , # Will be set by BaseTestWrapper
809
792
}
810
793
)
811
794
return BlockchainEngineXFixture (** fixture_data )
812
795
elif fixture_format == BlockchainEngineSyncFixture :
813
- # For sync fixture format
796
+ # Sync fixture format
797
+ assert genesis .header .block_hash != head_hash , (
798
+ "Invalid payload tests negative test via sync is not supported yet."
799
+ )
800
+ # Most clients require the header to start the sync process, so we create an empty
801
+ # block on top of the last block of the test to send it as new payload and trigger the
802
+ # sync process.
803
+ sync_built_block = self .generate_block_data (
804
+ t8n = t8n ,
805
+ fork = fork ,
806
+ block = Block (),
807
+ previous_env = env ,
808
+ previous_alloc = alloc ,
809
+ last_block = False ,
810
+ )
814
811
fixture_data .update (
815
812
{
816
- "payloads" : fixture_payloads ,
817
- "sync_payload" : sync_payload ,
813
+ "sync_payload" : sync_built_block .get_fixture_engine_new_payload (),
818
814
"pre" : pre ,
819
815
"post_state" : alloc if not self .exclude_full_post_state_in_output else None ,
820
816
}
@@ -824,8 +820,6 @@ def make_hive_fixture(
824
820
# Standard engine fixture
825
821
fixture_data .update (
826
822
{
827
- "payloads" : fixture_payloads ,
828
- "sync_payload" : sync_payload ,
829
823
"pre" : pre ,
830
824
"post_state" : alloc if not self .exclude_full_post_state_in_output else None ,
831
825
}
@@ -839,6 +833,10 @@ def generate(
839
833
fixture_format : FixtureFormat ,
840
834
) -> BaseFixture :
841
835
"""Generate the BlockchainTest fixture."""
836
+ # Skip sync fixture generation if verify_sync is False
837
+ if fixture_format == BlockchainEngineSyncFixture and not self .verify_sync :
838
+ raise pytest .skip ("Skipping sync fixture for test without verify_sync=True" )
839
+
842
840
t8n .reset_traces ()
843
841
if fixture_format in [
844
842
BlockchainEngineFixture ,
0 commit comments