Skip to content

Commit f9a4b42

Browse files
casperlabs-bors-ng[bot]EdHastingsCasperAssociationfizyk20
authored
Merge #4041
4041: Enable/disable voting in consensus when switching to/from Validate r=fizyk20 a=fizyk20 Closes #4037 Co-authored-by: Ed Hastings <[email protected]> Co-authored-by: Bartłomiej Kamiński <[email protected]>
2 parents 47af149 + 335563e commit f9a4b42

File tree

3 files changed

+175
-119
lines changed

3 files changed

+175
-119
lines changed

node/src/components/consensus/era_supervisor.rs

+84-27
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,20 @@ impl EraSupervisor {
222222
.len()
223223
.saturating_sub(PAST_EVIDENCE_ERAS as usize)
224224
.max(1);
225+
let old_current_era = self.current_era();
226+
let now = Timestamp::now();
225227
for i in (from..=relevant_switch_block_headers.len()).rev() {
226228
effects.extend(self.create_new_era_effects(
227229
effect_builder,
228230
rng,
229231
&relevant_switch_block_headers[..i],
232+
now,
230233
));
231234
}
235+
if self.current_era() != old_current_era {
236+
effects.extend(self.make_latest_era_current(effect_builder, rng, now));
237+
}
238+
effects.extend(self.activate_latest_era_if_needed(effect_builder, rng, now));
232239
Some(effects)
233240
}
234241

@@ -313,8 +320,9 @@ impl EraSupervisor {
313320
effect_builder: EffectBuilder<REv>,
314321
rng: &mut NodeRng,
315322
switch_blocks: &[BlockHeader],
323+
now: Timestamp,
316324
) -> Effects<Event> {
317-
match self.create_new_era(switch_blocks) {
325+
match self.create_new_era(switch_blocks, now) {
318326
Ok((era_id, outcomes)) => {
319327
self.handle_consensus_outcomes(effect_builder, rng, era_id, outcomes)
320328
}
@@ -327,17 +335,77 @@ impl EraSupervisor {
327335
}
328336
}
329337

338+
fn make_latest_era_current<REv: ReactorEventT>(
339+
&mut self,
340+
effect_builder: EffectBuilder<REv>,
341+
rng: &mut NodeRng,
342+
now: Timestamp,
343+
) -> Effects<Event> {
344+
let era_id = match self.current_era() {
345+
Some(era_id) => era_id,
346+
None => {
347+
return Effects::new();
348+
}
349+
};
350+
self.metrics
351+
.consensus_current_era
352+
.set(era_id.value() as i64);
353+
let start_height = self.era(era_id).start_height;
354+
self.next_block_height = self.next_block_height.max(start_height);
355+
let outcomes = self.era_mut(era_id).consensus.handle_is_current(now);
356+
self.handle_consensus_outcomes(effect_builder, rng, era_id, outcomes)
357+
}
358+
359+
fn activate_latest_era_if_needed<REv: ReactorEventT>(
360+
&mut self,
361+
effect_builder: EffectBuilder<REv>,
362+
rng: &mut NodeRng,
363+
now: Timestamp,
364+
) -> Effects<Event> {
365+
let era_id = match self.current_era() {
366+
Some(era_id) => era_id,
367+
None => {
368+
return Effects::new();
369+
}
370+
};
371+
if self.era(era_id).consensus.is_active() {
372+
return Effects::new();
373+
}
374+
let our_id = self.public_signing_key.clone();
375+
let outcomes = if !self.era(era_id).validators().contains_key(&our_id) {
376+
info!(era = era_id.value(), %our_id, "not voting; not a validator");
377+
vec![]
378+
} else {
379+
info!(era = era_id.value(), %our_id, "start voting");
380+
let secret = Keypair::new(self.secret_signing_key.clone(), our_id.clone());
381+
let instance_id = self.era(era_id).consensus.instance_id();
382+
let unit_hash_file = self.unit_file(instance_id);
383+
self.era_mut(era_id).consensus.activate_validator(
384+
our_id,
385+
secret,
386+
now,
387+
Some(unit_hash_file),
388+
)
389+
};
390+
self.handle_consensus_outcomes(effect_builder, rng, era_id, outcomes)
391+
}
392+
330393
/// Initializes a new era. The switch blocks must contain the most recent `auction_delay + 1`
331394
/// ones, in order, but at most as far back as to the last activation point.
332395
fn create_new_era(
333396
&mut self,
334397
switch_blocks: &[BlockHeader],
398+
now: Timestamp,
335399
) -> Result<(EraId, Vec<ProtocolOutcome<ClContext>>), CreateNewEraError> {
336400
let key_block = switch_blocks
337401
.last()
338402
.ok_or(CreateNewEraError::AttemptedToCreateEraWithNoSwitchBlocks)?;
339403
let era_id = key_block.era_id().successor();
340404

405+
let chainspec_hash = self.chainspec.hash();
406+
let key_block_hash = key_block.block_hash();
407+
let instance_id = instance_id(chainspec_hash, era_id, key_block_hash);
408+
341409
if self.open_eras.contains_key(&era_id) {
342410
debug!(era = era_id.value(), "era already exists");
343411
return Ok((era_id, vec![]));
@@ -409,11 +477,6 @@ impl EraSupervisor {
409477
.flat_map(|era_end| era_end.era_report().equivocators.clone())
410478
.collect();
411479

412-
let chainspec_hash = self.chainspec.hash();
413-
let key_block_hash = key_block.block_hash();
414-
let instance_id = instance_id(chainspec_hash, era_id, key_block_hash);
415-
let now = Timestamp::now();
416-
417480
info!(
418481
?validators,
419482
%start_time,
@@ -437,7 +500,7 @@ impl EraSupervisor {
437500
.collect();
438501

439502
// Create and insert the new era instance.
440-
let (consensus, mut outcomes) = match self.chainspec.core_config.consensus_protocol {
503+
let (consensus, outcomes) = match self.chainspec.core_config.consensus_protocol {
441504
ConsensusProtocolName::Highway => HighwayProtocol::new_boxed(
442505
instance_id,
443506
validators.clone(),
@@ -477,7 +540,6 @@ impl EraSupervisor {
477540

478541
// Activate the era if this node was already running when the era began, it is still
479542
// ongoing based on its minimum duration, and we are one of the validators.
480-
let our_id = self.public_signing_key.clone();
481543
if self
482544
.current_era()
483545
.map_or(false, |current_era| current_era > era_id)
@@ -492,25 +554,6 @@ impl EraSupervisor {
492554
if let Some(era) = self.open_eras.get_mut(&era_id) {
493555
era.consensus.set_evidence_only();
494556
}
495-
} else {
496-
self.metrics
497-
.consensus_current_era
498-
.set(era_id.value() as i64);
499-
self.next_block_height = self.next_block_height.max(start_height);
500-
outcomes.extend(self.era_mut(era_id).consensus.handle_is_current(now));
501-
if !self.era(era_id).validators().contains_key(&our_id) {
502-
info!(era = era_id.value(), %our_id, "not voting; not a validator");
503-
} else {
504-
info!(era = era_id.value(), %our_id, "start voting");
505-
let secret = Keypair::new(self.secret_signing_key.clone(), our_id.clone());
506-
let unit_hash_file = self.unit_file(&instance_id);
507-
outcomes.extend(self.era_mut(era_id).consensus.activate_validator(
508-
our_id,
509-
secret,
510-
now,
511-
Some(unit_hash_file),
512-
))
513-
};
514557
}
515558

516559
// Mark validators as faulty for which we have evidence in the previous era.
@@ -809,6 +852,20 @@ impl EraSupervisor {
809852
}
810853
}
811854

855+
/// Will deactivate voting for the current era.
856+
/// Does nothing if the current era doesn't exist or is inactive already.
857+
pub(crate) fn deactivate_current_era(&mut self) -> Result<EraId, String> {
858+
let which_era = self
859+
.current_era()
860+
.ok_or_else(|| "attempt to deactivate an era with no eras instantiated!".to_string())?;
861+
let era = self.era_mut(which_era);
862+
if false == era.consensus.is_active() {
863+
return Err(format!("attempt to deactivate inactive era {}", which_era));
864+
}
865+
era.consensus.deactivate_validator();
866+
Ok(which_era)
867+
}
868+
812869
pub(super) fn resolve_validity<REv: ReactorEventT>(
813870
&mut self,
814871
effect_builder: EffectBuilder<REv>,

0 commit comments

Comments
 (0)