diff --git a/program-tests/registry-test/tests/test_register_anytime.rs b/program-tests/registry-test/tests/test_register_anytime.rs new file mode 100644 index 0000000000..0971c61819 --- /dev/null +++ b/program-tests/registry-test/tests/test_register_anytime.rs @@ -0,0 +1,93 @@ +use forester_utils::forester_epoch::Epoch; +use light_program_test::{ + program_test::{LightProgramTest, TestRpc}, + ProgramTestConfig, +}; +use light_registry::{ + protocol_config::state::{ProtocolConfig, ProtocolConfigPda}, + ForesterConfig, ForesterEpochPda, +}; +use light_test_utils::{ + assert_epoch::{assert_epoch_pda, assert_registered_forester_pda}, + register_test_forester, Rpc, +}; +use serial_test::serial; +use solana_sdk::{signature::Keypair, signer::Signer}; + +/// Verifies that foresters can register for an epoch outside the original +/// registration window (slots 0-99 with default config). Previously this +/// would fail with `NotInRegistrationPeriod`. +#[serial] +#[tokio::test] +async fn test_forester_register_outside_registration_phase() { + let config = ProgramTestConfig { + protocol_config: ProtocolConfig::default(), + with_prover: false, + with_forester: false, + ..Default::default() + }; + let mut rpc = LightProgramTest::new(config).await.unwrap(); + rpc.indexer = None; + let env = rpc.test_accounts.clone(); + + let forester_keypair = Keypair::new(); + rpc.airdrop_lamports(&forester_keypair.pubkey(), 1_000_000_000) + .await + .unwrap(); + + // Register the base forester PDA. + register_test_forester( + &mut rpc, + &env.protocol.governance_authority, + &forester_keypair.pubkey(), + ForesterConfig { fee: 1 }, + ) + .await + .unwrap(); + + let protocol_config = rpc + .get_anchor_account::(&env.protocol.governance_authority_pda) + .await + .unwrap() + .unwrap() + .config; + + // Warp to slot 500 -- well past the old registration window (0-99). + // With ProtocolConfig::default() the active phase starts at slot 100. + rpc.warp_to_slot(500).unwrap(); + + // Register for epoch 0 with explicit epoch to bypass client-side + // auto-detection (which would skip if not in registration phase). + let registered_epoch = Epoch::register( + &mut rpc, + &protocol_config, + &forester_keypair, + &forester_keypair.pubkey(), + Some(0), + ) + .await + .unwrap(); + + assert!( + registered_epoch.is_some(), + "Forester should be able to register outside the original registration window" + ); + let registered_epoch = registered_epoch.unwrap(); + + let forester_epoch_pda = rpc + .get_anchor_account::(®istered_epoch.forester_epoch_pda) + .await + .unwrap() + .unwrap(); + assert_eq!(forester_epoch_pda.epoch, 0); + assert!(forester_epoch_pda.total_epoch_weight.is_none()); + + assert_epoch_pda(&mut rpc, 0, 1).await; + assert_registered_forester_pda( + &mut rpc, + ®istered_epoch.forester_epoch_pda, + &forester_keypair.pubkey(), + 0, + ) + .await; +} diff --git a/programs/registry/src/protocol_config/state.rs b/programs/registry/src/protocol_config/state.rs index eaaa41b2b1..d3094498a8 100644 --- a/programs/registry/src/protocol_config/state.rs +++ b/programs/registry/src/protocol_config/state.rs @@ -184,12 +184,16 @@ impl ProtocolConfig { /// In the last part of the active phase the registration phase starts. /// Returns end slot of the registration phase/start slot of the next active phase. + /// Registration phase time check is temporarily disabled to allow + /// foresters to register for the current epoch at any time. pub fn is_registration_phase(&self, slot: u64) -> Result { let latest_register_epoch = self.get_latest_register_epoch(slot)?; + /* let latest_register_epoch_progress = self.get_latest_register_epoch_progress(slot)?; if latest_register_epoch_progress >= self.registration_phase_length { return err!(RegistryError::NotInRegistrationPeriod); - } + } */ + Ok((latest_register_epoch) * self.active_phase_length + self.genesis_slot + self.registration_phase_length) diff --git a/sdk-tests/csdk-anchor-full-derived-test/tests/integration_tests.rs b/sdk-tests/csdk-anchor-full-derived-test/tests/integration_tests.rs index 9b40b900e5..2c3e82972a 100644 --- a/sdk-tests/csdk-anchor-full-derived-test/tests/integration_tests.rs +++ b/sdk-tests/csdk-anchor-full-derived-test/tests/integration_tests.rs @@ -3863,7 +3863,7 @@ async fn test_d9_edge_many_literals() { #[tokio::test] async fn test_d9_edge_mixed() { use csdk_anchor_full_derived_test::d9_seeds::{ - edge_cases::{AB, SEED_123, _UNDERSCORE_CONST}, + edge_cases::{_UNDERSCORE_CONST, AB, SEED_123}, D9EdgeMixedParams, };