mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-06-05 06:20:27 +08:00
Run DKG even if out of vote window
Signed-off-by: Jacinta Ferrant <jacinta@trustmachines.co>
This commit is contained in:
@@ -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<bool, ClientError> {
|
||||
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<RewardSet, ClientError> {
|
||||
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<u8> = rng.sample_iter(Standard).take(20).collect();
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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(())
|
||||
|
||||
Reference in New Issue
Block a user