From ce6be782138765faea6ae60c3edb12673dd4acf8 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Wed, 7 Feb 2024 15:55:05 -0800 Subject: [PATCH] Run DKG even if out of vote window Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/stacks_client.rs | 64 ----------------------- stacks-signer/src/runloop.rs | 2 + stacks-signer/src/signer.rs | 15 ++---- 3 files changed, 7 insertions(+), 74 deletions(-) diff --git a/stacks-signer/src/client/stacks_client.rs b/stacks-signer/src/client/stacks_client.rs index f84ed44d6..863942655 100644 --- a/stacks-signer/src/client/stacks_client.rs +++ b/stacks-signer/src/client/stacks_client.rs @@ -345,23 +345,6 @@ impl StacksClient { Ok(pox_info.next_cycle.prepare_phase_start_block_height < stacks_tip_height) } - /// Check whether the given reward cycle is in the prepare phase - pub fn reward_cycle_in_vote_window(&self, reward_cycle: u64) -> Result { - let pox_info = self.get_pox_data()?; - if reward_cycle == pox_info.reward_cycle_id.wrapping_add(1) { - let peer_info = self.get_peer_info()?; - let stacks_tip_height = peer_info.stacks_tip_height; - // The vote window starts at the second block of the prepare phase hence the + 1. - let vote_window_start = pox_info - .next_cycle - .prepare_phase_start_block_height - .wrapping_add(1); - Ok(stacks_tip_height >= vote_window_start) - } else { - // We are not in the prepare phase of the reward cycle as the upcoming cycle does not match - Ok(false) - } - } /// Get the reward set from the stacks node for the given reward cycle pub fn get_reward_set(&self, reward_cycle: u64) -> Result { debug!("Getting reward set for reward cycle {reward_cycle}..."); @@ -1287,53 +1270,6 @@ mod tests { assert!(!h.join().unwrap().unwrap()); } - #[test] - #[serial] - fn reward_cycle_in_vote_window() { - let consensus_hash = "64c8c3049ff6b939c65828e3168210e6bb32d880".to_string(); - - // Should return FALSE as the passed in reward cycle is old - let mock = MockServerClient::new(); - let pox_response = build_get_pox_data_response(2, 10); - let h = spawn(move || mock.client.reward_cycle_in_vote_window(0)); - write_response(mock.server, pox_response.as_bytes()); - assert!(!h.join().unwrap().unwrap()); - - // Should return FALSE as the passed in reward cycle is NEWER than the NEXT reward cycle of the node - let mock = MockServerClient::new(); - let pox_response = build_get_pox_data_response(2, 10); - let h = spawn(move || mock.client.reward_cycle_in_vote_window(4)); - write_response(mock.server, pox_response.as_bytes()); - assert!(!h.join().unwrap().unwrap()); - - // Should return FALSE as the passed in reward cycle is the same as the current reward cycle - let mock = MockServerClient::new(); - let pox_response = build_get_pox_data_response(2, 10); - let h = spawn(move || mock.client.reward_cycle_in_vote_window(2)); - write_response(mock.server, pox_response.as_bytes()); - assert!(!h.join().unwrap().unwrap()); - - // Should return FALSE as the passed in reward cycle is the NEXT reward cycle BUT the prepare phase is in its FIRST block - let mock = MockServerClient::new(); - let pox_response = build_get_pox_data_response(2, 11); - let peer_response = build_get_peer_info_response(11, consensus_hash.clone()); - let h = spawn(move || mock.client.reward_cycle_in_vote_window(3)); - write_response(mock.server, pox_response.as_bytes()); - let mock = MockServerClient::from_config(mock.config); - write_response(mock.server, peer_response.as_bytes()); - assert!(!h.join().unwrap().unwrap()); - - // Should return TRUE as the passed in reward cycle is the NEXT reward cycle AND the prepare phase is in its SECOND block - let mock = MockServerClient::new(); - let pox_response = build_get_pox_data_response(2, 10); - let peer_response = build_get_peer_info_response(11, consensus_hash.clone()); - let h = spawn(move || mock.client.reward_cycle_in_vote_window(3)); - write_response(mock.server, pox_response.as_bytes()); - let mock = MockServerClient::from_config(mock.config); - write_response(mock.server, peer_response.as_bytes()); - assert!(h.join().unwrap().unwrap()); - } - fn generate_random_consensus_hash() -> String { let rng = rand::thread_rng(); let bytes: Vec = rng.sample_iter(Standard).take(20).collect(); diff --git a/stacks-signer/src/runloop.rs b/stacks-signer/src/runloop.rs index 1d33e7278..c71c2723d 100644 --- a/stacks-signer/src/runloop.rs +++ b/stacks-signer/src/runloop.rs @@ -243,6 +243,8 @@ impl RunLoop { if self.stacks_signers.is_empty() { info!("Signer is not registered for the current or next reward cycle. Waiting for confirmed registration..."); return Err(backoff::Error::transient(ClientError::NotRegistered)); + } else { + info!("Runloop successfully initialized!"); } self.state = State::Initialized; Ok(()) diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index e11b778f8..f688a7c94 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -1041,31 +1041,26 @@ impl Signer { /// Update the DKG for the provided signer info, triggering it if required pub fn update_dkg(&mut self) -> Result<(), ClientError> { + debug!("Signer #{}: Checking DKG...", self.signer_id); let reward_cycle = self.reward_cycle; let aggregate_public_key = self.stacks_client.get_aggregate_public_key(reward_cycle)?; - let in_vote_window = self - .stacks_client - .reward_cycle_in_vote_window(reward_cycle)?; self.coordinator .set_aggregate_public_key(aggregate_public_key); let coordinator_id = self .stacks_client .calculate_coordinator(&self.signing_round.public_keys) .0; - // TODO: should we attempt to vote anyway if out of window? what if we didn't successfully run DKG in prepare phase? - if in_vote_window - && aggregate_public_key.is_none() + if aggregate_public_key.is_none() && self.signer_id == coordinator_id && self.coordinator.state == CoordinatorState::Idle { - info!("Signer is the coordinator and is in the prepare phase for reward cycle {reward_cycle}. Triggering a DKG round..."); + info!("Signer #{}: Is the current coordinator for {reward_cycle}. Triggering a DKG round...", self.signer_id); self.commands.push_back(Command::Dkg); } else { - debug!("Not updating dkg"; - "in_vote_window" => in_vote_window, + debug!("Signer #{}: Not triggering a DKG round.", self.signer_id; "aggregate_public_key" => aggregate_public_key.is_some(), - "signer_id" => self.signer_id, "coordinator_id" => coordinator_id, + "coordinator_idle" => self.coordinator.state == CoordinatorState::Idle, ); } Ok(())