diff --git a/parachain/modules/consensus/sync-committee/primitives/src/types.rs b/parachain/modules/consensus/sync-committee/primitives/src/types.rs index 963ffb8cf..1fc0b4d59 100644 --- a/parachain/modules/consensus/sync-committee/primitives/src/types.rs +++ b/parachain/modules/consensus/sync-committee/primitives/src/types.rs @@ -94,6 +94,8 @@ pub struct VerifierState { pub current_sync_committee: SyncCommittee, /// Committee for the next sync period pub next_sync_committee: SyncCommittee, + /// state_period + pub state_period: u64, } /// Finalized header proof diff --git a/parachain/modules/consensus/sync-committee/primitives/src/util.rs b/parachain/modules/consensus/sync-committee/primitives/src/util.rs index 7adb46c03..92a48433d 100644 --- a/parachain/modules/consensus/sync-committee/primitives/src/util.rs +++ b/parachain/modules/consensus/sync-committee/primitives/src/util.rs @@ -13,7 +13,7 @@ use ssz_rs::prelude::*; /// Returns true if sync committee update is required pub fn should_have_sync_committee_update(state_period: u64, signature_period: u64) -> bool { - state_period != signature_period + signature_period == state_period + 1 } /// Return the sync committee period at the given ``epoch`` diff --git a/parachain/modules/consensus/sync-committee/prover/src/lib.rs b/parachain/modules/consensus/sync-committee/prover/src/lib.rs index 5e3f62dae..7634e2d5c 100644 --- a/parachain/modules/consensus/sync-committee/prover/src/lib.rs +++ b/parachain/modules/consensus/sync-committee/prover/src/lib.rs @@ -229,7 +229,7 @@ impl SyncCommitteeProver { /// we use `head` pub async fn fetch_light_client_update( &self, - client_state: VerifierState, + mut client_state: VerifierState, finality_checkpoint: Checkpoint, latest_block_id: Option<&str>, debug_target: &str, @@ -251,8 +251,7 @@ impl SyncCommitteeProver { }; let mut block = self.fetch_block(&get_block_id(latest_root)).await?; let min_signatures = (2 * SYNC_COMMITTEE_SIZE) / 3; - let state_period = - compute_sync_committee_period_at_slot(client_state.finalized_header.slot); + let state_period = client_state.state_period; loop { // Some checks on the epoch finalized by the signature block let parent_root = block.parent_root; @@ -298,8 +297,13 @@ impl SyncCommitteeProver { let execution_payload_proof = prove_execution_payload(&mut finalized_state)?; let signature_period = compute_sync_committee_period_at_slot(block.slot); + let client_state_next_sync_committee_root = + client_state.next_sync_committee.hash_tree_root()?; + let attested_state_current_sync_committee_root = + attested_state.current_sync_committee.hash_tree_root()?; let sync_committee_update = - if should_have_sync_committee_update(state_period, signature_period) { + // We must make sure we switch the sync comittee only when the finalized header has changed sync committees + if should_have_sync_committee_update(state_period, signature_period) && client_state_next_sync_committee_root == attested_state_current_sync_committee_root { let sync_committee_proof = prove_sync_committee_update(&mut attested_state)?; Some(SyncCommitteeUpdate { next_sync_committee: attested_state.next_sync_committee, diff --git a/parachain/modules/consensus/sync-committee/prover/src/test.rs b/parachain/modules/consensus/sync-committee/prover/src/test.rs index abfed1f83..9dabf9149 100644 --- a/parachain/modules/consensus/sync-committee/prover/src/test.rs +++ b/parachain/modules/consensus/sync-committee/prover/src/test.rs @@ -261,6 +261,7 @@ async fn test_client_sync() { latest_finalized_epoch: compute_epoch_at_slot(block_header.slot), current_sync_committee: state.current_sync_committee, next_sync_committee: state.next_sync_committee, + state_period: 810, }; let mut next_period = start_period + 1; @@ -280,7 +281,6 @@ async fn test_client_sync() { #[cfg(test)] #[allow(non_snake_case)] #[tokio::test] -#[ignore] async fn test_sync_committee_hand_offs() { let sync_committee_prover = setup_prover(); let state_period = 805; @@ -299,6 +299,7 @@ async fn test_sync_committee_hand_offs() { latest_finalized_epoch: compute_epoch_at_slot(block_header.slot), current_sync_committee: state.current_sync_committee, next_sync_committee: state.next_sync_committee, + state_period: 805, }; // Verify an update from state_period + 1 @@ -326,7 +327,7 @@ async fn test_sync_committee_hand_offs() { .unwrap(); assert!(update.sync_committee_update.is_some()); client_state = verify_sync_committee_attestation(client_state, update).unwrap(); - + assert_eq!(client_state.state_period, state_period + 1); // Verify block in the current state_period let latest_block_id = { let slot = ((signature_period * EPOCHS_PER_SYNC_COMMITTEE_PERIOD) * SLOTS_PER_EPOCH) + @@ -384,6 +385,7 @@ async fn test_prover() { latest_finalized_epoch: compute_epoch_at_slot(block_header.slot), current_sync_committee: state.current_sync_committee, next_sync_committee: state.next_sync_committee, + state_period: compute_sync_committee_period_at_slot(block_header.slot), }; let mut count = 0; @@ -504,7 +506,6 @@ pub struct EventResponse { fn setup_prover() -> SyncCommitteeProver { dotenv::dotenv().ok(); - let consensus_url = - std::env::var("CONSENSUS_NODE_URL").unwrap_or("http://localhost:3500".to_string()); + let consensus_url = std::env::var("BEACON_URL").unwrap_or("http://localhost:3500".to_string()); SyncCommitteeProver::new(consensus_url) } diff --git a/parachain/modules/consensus/sync-committee/verifier/src/lib.rs b/parachain/modules/consensus/sync-committee/verifier/src/lib.rs index 9b35bf6a4..3ba442011 100644 --- a/parachain/modules/consensus/sync-committee/verifier/src/lib.rs +++ b/parachain/modules/consensus/sync-committee/verifier/src/lib.rs @@ -59,7 +59,7 @@ pub fn verify_sync_committee_attestation( ))? } - let state_period = compute_sync_committee_period_at_slot(trusted_state.finalized_header.slot); + let state_period = trusted_state.state_period; let update_signature_period = compute_sync_committee_period_at_slot(update.signature_slot); if !(state_period..=state_period + 1).contains(&update_signature_period) { Err(Error::InvalidUpdate("State period does not contain signature period".into()))? @@ -192,6 +192,7 @@ pub fn verify_sync_committee_attestation( latest_finalized_epoch: update.finality_proof.epoch, current_sync_committee: trusted_state.next_sync_committee, next_sync_committee: sync_committee_update.next_sync_committee, + state_period: state_period + 1, } } else { Err(Error::InvalidUpdate("Expected sync committee update to be present".into()))?