@@ -2556,6 +2556,111 @@ def test_gossip_execution_payload_bid__reject_incorrect_prev_randao(spec, state)
25562556 yield "messages" , "meta" , messages
25572557
25582558
2559+ @with_gloas_and_later
2560+ @spec_state_test_with_matching_config
2561+ def test_gossip_execution_payload_bid__reject_block_hash_equals_parent_block_hash (spec , state ):
2562+ """A bid whose block_hash equals its parent_block_hash is rejected."""
2563+ anchor_state = state .copy ()
2564+ yield "topic" , "meta" , "execution_payload_bid"
2565+
2566+ store , blocks , parent_root = setup_store_advanced_for_bid (spec , state )
2567+ finalized_checkpoint_meta = activate_builders (spec , state , store , blocks )
2568+ head_payload = record_head_payload (spec , state , store , blocks )
2569+ yield "state" , anchor_state
2570+ for signed in blocks :
2571+ yield get_filename (signed ), signed
2572+ yield "blocks" , "meta" , get_blocks_meta (blocks , head_payload )
2573+ yield "finalized_checkpoint" , "meta" , finalized_checkpoint_meta
2574+
2575+ seen = get_seen (spec )
2576+ time_ms = spec .compute_time_at_slot_ms (store , state .slot )
2577+ yield "current_time_ms" , "meta" , int (time_ms )
2578+ messages = []
2579+
2580+ common_fee = spec .ExecutionAddress (b"\x11 " * 20 )
2581+ parent_gas_limit = state .latest_execution_payload_bid .gas_limit
2582+ time_ms += 50
2583+ proposal_slot , validator_index = find_upcoming_proposal_slot (spec , state )
2584+ signed_prefs = build_signed_proposer_preferences (
2585+ spec ,
2586+ state ,
2587+ proposal_slot = proposal_slot ,
2588+ validator_index = validator_index ,
2589+ fee_recipient = common_fee ,
2590+ target_gas_limit = parent_gas_limit ,
2591+ )
2592+ yield get_filename (signed_prefs ), signed_prefs
2593+ result , reason = run_validate_gossip (
2594+ spec ,
2595+ seen = seen ,
2596+ store = store ,
2597+ signed_proposer_preferences = signed_prefs ,
2598+ current_time_ms = time_ms ,
2599+ )
2600+ assert result == "valid"
2601+ assert reason is None
2602+ messages .append (
2603+ {
2604+ "current_time_ms" : int (time_ms ),
2605+ "message" : get_filename (signed_prefs ),
2606+ "expected" : result ,
2607+ }
2608+ )
2609+
2610+ time_ms += 10
2611+ yield get_filename (head_payload ), head_payload
2612+ result , reason = run_validate_gossip (
2613+ spec , seen = seen , store = store , signed_execution_payload_envelope = head_payload
2614+ )
2615+ assert result == "valid"
2616+ assert reason is None
2617+ messages .append (
2618+ {
2619+ "current_time_ms" : int (time_ms ),
2620+ "message" : get_filename (head_payload ),
2621+ "expected" : result ,
2622+ }
2623+ )
2624+
2625+ # All other checks pass and only block_hash is wrong: it equals the
2626+ # parent_block_hash, which a real execution payload can never produce.
2627+ parent_block_hash = head_payload .message .payload .block_hash
2628+ signed_bid = build_signed_bid (
2629+ spec ,
2630+ state ,
2631+ builder_index = spec .BuilderIndex (0 ),
2632+ slot = proposal_slot ,
2633+ parent_block_hash = parent_block_hash ,
2634+ parent_block_root = parent_root ,
2635+ fee_recipient = common_fee ,
2636+ gas_limit = parent_gas_limit ,
2637+ value = spec .Gwei (1 ),
2638+ block_hash = parent_block_hash ,
2639+ )
2640+ yield get_filename (signed_bid ), signed_bid
2641+
2642+ time_ms += 40
2643+ result , reason = run_validate_gossip (
2644+ spec ,
2645+ seen = seen ,
2646+ store = store ,
2647+ signed_execution_payload_bid = signed_bid ,
2648+ current_time_ms = time_ms ,
2649+ )
2650+ assert result == "reject"
2651+ assert reason == "bid's block hash equals its parent block hash"
2652+ messages .append (
2653+ {
2654+ "current_time_ms" : int (time_ms ),
2655+ "message" : get_filename (signed_bid ),
2656+ "expected" : result ,
2657+ "reason" : reason ,
2658+ }
2659+ )
2660+
2661+ yield "messages" , "meta" , messages
2662+
2663+
25592664@with_gloas_and_later
25602665@spec_state_test_with_matching_config
25612666def test_gossip_execution_payload_bid__reject_invalid_signature (spec , state ):
0 commit comments