@@ -13,7 +13,11 @@ use beacon_chain::test_utils::{
1313use beacon_chain:: {
1414 BeaconChain , BeaconChainError , BeaconChainTypes , BeaconSnapshot , BlockError , ChainConfig ,
1515 NotifyExecutionLayer , ServerSentEventHandler , WhenSlotSkipped ,
16- data_availability_checker:: MaybeAvailableBlock , historical_blocks:: HistoricalBlockError ,
16+ beacon_proposer_cache:: {
17+ compute_proposer_duties_from_head, ensure_state_can_determine_proposers_for_epoch,
18+ } ,
19+ data_availability_checker:: MaybeAvailableBlock ,
20+ historical_blocks:: HistoricalBlockError ,
1721 migrate:: MigratorConfig ,
1822} ;
1923use logging:: create_test_tracing_subscriber;
@@ -1273,19 +1277,34 @@ async fn proposer_shuffling_root_consistency_test(
12731277#[ tokio:: test]
12741278async fn proposer_shuffling_root_consistency_same_epoch ( ) {
12751279 let spec = test_spec :: < E > ( ) ;
1276- proposer_shuffling_root_consistency_test ( spec, 32 , 39 ) . await ;
1280+ proposer_shuffling_root_consistency_test (
1281+ spec,
1282+ 4 * E :: slots_per_epoch ( ) ,
1283+ 5 * E :: slots_per_epoch ( ) - 1 ,
1284+ )
1285+ . await ;
12771286}
12781287
12791288#[ tokio:: test]
12801289async fn proposer_shuffling_root_consistency_next_epoch ( ) {
12811290 let spec = test_spec :: < E > ( ) ;
1282- proposer_shuffling_root_consistency_test ( spec, 32 , 47 ) . await ;
1291+ proposer_shuffling_root_consistency_test (
1292+ spec,
1293+ 4 * E :: slots_per_epoch ( ) ,
1294+ 6 * E :: slots_per_epoch ( ) - 1 ,
1295+ )
1296+ . await ;
12831297}
12841298
12851299#[ tokio:: test]
12861300async fn proposer_shuffling_root_consistency_two_epochs ( ) {
12871301 let spec = test_spec :: < E > ( ) ;
1288- proposer_shuffling_root_consistency_test ( spec, 32 , 55 ) . await ;
1302+ proposer_shuffling_root_consistency_test (
1303+ spec,
1304+ 4 * E :: slots_per_epoch ( ) ,
1305+ 7 * E :: slots_per_epoch ( ) - 1 ,
1306+ )
1307+ . await ;
12891308}
12901309
12911310#[ tokio:: test]
@@ -1501,6 +1520,120 @@ async fn proposer_shuffling_changing_with_lookahead() {
15011520 ) ;
15021521}
15031522
1523+ #[ tokio:: test]
1524+ async fn proposer_duties_from_head_fulu ( ) {
1525+ let spec = ForkName :: Fulu . make_genesis_spec ( E :: default_spec ( ) ) ;
1526+
1527+ let db_path = tempdir ( ) . unwrap ( ) ;
1528+ let store = get_store_generic ( & db_path, Default :: default ( ) , spec. clone ( ) ) ;
1529+ let validators_keypairs =
1530+ types:: test_utils:: generate_deterministic_keypairs ( LOW_VALIDATOR_COUNT ) ;
1531+ let harness = TestHarness :: builder ( MinimalEthSpec )
1532+ . spec ( spec. into ( ) )
1533+ . keypairs ( validators_keypairs)
1534+ . fresh_disk_store ( store)
1535+ . mock_execution_layer ( )
1536+ . build ( ) ;
1537+ let spec = & harness. chain . spec ;
1538+
1539+ let initial_blocks = E :: slots_per_epoch ( ) * 3 ;
1540+
1541+ // Build chain out to parent block.
1542+ let initial_slots: Vec < Slot > = ( 1 ..=initial_blocks) . map ( Into :: into) . collect ( ) ;
1543+ let ( state, state_root) = harness. get_current_state_and_root ( ) ;
1544+ let all_validators = harness. get_all_validators ( ) ;
1545+ let ( _, _, head_block_root, head_state) = harness
1546+ . add_attested_blocks_at_slots ( state, state_root, & initial_slots, & all_validators)
1547+ . await ;
1548+
1549+ // Compute the proposer duties at the next epoch from the head
1550+ let next_epoch = head_state. next_epoch ( ) . unwrap ( ) ;
1551+ let ( _indices, dependent_root, _, fork) =
1552+ compute_proposer_duties_from_head ( next_epoch, & harness. chain ) . unwrap ( ) ;
1553+
1554+ assert_eq ! (
1555+ dependent_root,
1556+ head_state
1557+ . proposer_shuffling_decision_root_at_epoch( next_epoch, head_block_root. into( ) , spec)
1558+ . unwrap( )
1559+ ) ;
1560+ assert_eq ! ( fork, head_state. fork( ) ) ;
1561+ }
1562+
1563+ /// Test that we can compute the proposer shuffling for the Gloas fork epoch itself using lookahead!
1564+ #[ tokio:: test]
1565+ async fn proposer_lookahead_gloas_fork_epoch ( ) {
1566+ let gloas_fork_epoch = Epoch :: new ( 4 ) ;
1567+ let mut spec = ForkName :: Fulu . make_genesis_spec ( E :: default_spec ( ) ) ;
1568+ spec. gloas_fork_epoch = Some ( gloas_fork_epoch) ;
1569+
1570+ let db_path = tempdir ( ) . unwrap ( ) ;
1571+ let store = get_store_generic ( & db_path, Default :: default ( ) , spec. clone ( ) ) ;
1572+ let validators_keypairs =
1573+ types:: test_utils:: generate_deterministic_keypairs ( LOW_VALIDATOR_COUNT ) ;
1574+ let harness = TestHarness :: builder ( E :: default ( ) )
1575+ . spec ( spec. into ( ) )
1576+ . keypairs ( validators_keypairs)
1577+ . fresh_disk_store ( store)
1578+ . mock_execution_layer ( )
1579+ . build ( ) ;
1580+ let spec = & harness. chain . spec ;
1581+
1582+ let initial_blocks = ( gloas_fork_epoch - 1 )
1583+ . start_slot ( E :: slots_per_epoch ( ) )
1584+ . as_u64 ( ) ;
1585+
1586+ // Build chain out to parent block.
1587+ let initial_slots: Vec < Slot > = ( 1 ..=initial_blocks) . map ( Into :: into) . collect ( ) ;
1588+ let ( state, state_root) = harness. get_current_state_and_root ( ) ;
1589+ let all_validators = harness. get_all_validators ( ) ;
1590+ let ( _, _, head_block_root, mut head_state) = harness
1591+ . add_attested_blocks_at_slots ( state, state_root, & initial_slots, & all_validators)
1592+ . await ;
1593+ let head_state_root = head_state. canonical_root ( ) . unwrap ( ) ;
1594+
1595+ // Check that we have access to the next epoch shuffling according to
1596+ // `ensure_state_can_determine_proposers_for_epoch`.
1597+ ensure_state_can_determine_proposers_for_epoch (
1598+ & mut head_state,
1599+ head_state_root,
1600+ gloas_fork_epoch,
1601+ spec,
1602+ )
1603+ . unwrap ( ) ;
1604+ assert_eq ! ( head_state. current_epoch( ) , gloas_fork_epoch - 1 ) ;
1605+
1606+ // Compute the proposer duties at the fork epoch from the head.
1607+ let ( indices, dependent_root, _, fork) =
1608+ compute_proposer_duties_from_head ( gloas_fork_epoch, & harness. chain ) . unwrap ( ) ;
1609+
1610+ assert_eq ! (
1611+ dependent_root,
1612+ head_state
1613+ . proposer_shuffling_decision_root_at_epoch(
1614+ gloas_fork_epoch,
1615+ head_block_root. into( ) ,
1616+ spec
1617+ )
1618+ . unwrap( )
1619+ ) ;
1620+ assert_ne ! ( fork, head_state. fork( ) ) ;
1621+ assert_eq ! ( fork, spec. fork_at_epoch( gloas_fork_epoch) ) ;
1622+
1623+ // Build a block in the Gloas fork epoch and assert that the shuffling does not change.
1624+ let gloas_slots = vec ! [ gloas_fork_epoch. start_slot( E :: slots_per_epoch( ) ) ] ;
1625+ let ( _, _, _, _) = harness
1626+ . add_attested_blocks_at_slots ( head_state, head_state_root, & gloas_slots, & all_validators)
1627+ . await ;
1628+
1629+ let ( no_lookahead_indices, no_lookahead_dependent_root, _, no_lookahead_fork) =
1630+ compute_proposer_duties_from_head ( gloas_fork_epoch, & harness. chain ) . unwrap ( ) ;
1631+
1632+ assert_eq ! ( no_lookahead_indices, indices) ;
1633+ assert_eq ! ( no_lookahead_dependent_root, dependent_root) ;
1634+ assert_eq ! ( no_lookahead_fork, fork) ;
1635+ }
1636+
15041637// Ensure blocks from abandoned forks are pruned from the Hot DB
15051638#[ tokio:: test]
15061639async fn prunes_abandoned_fork_between_two_finalized_checkpoints ( ) {
0 commit comments