Skip to content

Commit

Permalink
Merge pull request #2352 from dusk-network/relax-iterations
Browse files Browse the repository at this point in the history
consensus: relax emergency iterations checks
  • Loading branch information
herr-seppia authored Sep 12, 2024
2 parents 1c7e7dd + bac087b commit 8dbdd84
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 34 deletions.
38 changes: 29 additions & 9 deletions consensus/src/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::config::EMERGENCY_MODE_ITERATION_THRESHOLD;
use crate::user::cluster::Cluster;
use crate::user::committee::Committee;
use dusk_bytes::Serializable;
Expand All @@ -17,7 +18,7 @@ use node_data::message::StepMessage;
use std::collections::{BTreeMap, HashMap};
use std::fmt;
use thiserror::Error;
use tracing::{debug, error};
use tracing::{debug, error, warn};

/// Aggregator collects votes for Validation and Ratification steps by
/// mapping step numbers and [StepVote] to both an aggregated signature and a
Expand Down Expand Up @@ -81,8 +82,19 @@ impl<V: StepVote> Aggregator<V> {
v: &V,
) -> Result<(StepVotes, bool), AggregatorError<V>> {
let sign_info = v.sign_info();

let iter = v.header().iteration;

let emergency = iter >= EMERGENCY_MODE_ITERATION_THRESHOLD;

let msg_step = v.get_step();
let vote = v.vote();
if emergency && !vote.is_valid() {
warn!(
"Vote {vote:?} for iter {iter} skipped due to emergency mode",
);
return Ok((StepVotes::default(), false));
}

let signature = sign_info.signature.inner();
let signer = &sign_info.signer;
Expand All @@ -109,14 +121,18 @@ impl<V: StepVote> Aggregator<V> {
return Err(AggregatorError::DuplicatedVote);
}

// Check if the provisioner voted for a different result
let voters_list = self.uniqueness.entry(msg_step).or_default();
match voters_list.get(signer.bytes()) {
None => voters_list.insert(*signer.bytes(), v.clone()),
Some(prev_vote) => {
return Err(AggregatorError::ConflictingVote(prev_vote.clone()))
}
};
if v.header().iteration < EMERGENCY_MODE_ITERATION_THRESHOLD {
// Check if the provisioner voted for a different result
let voters_list = self.uniqueness.entry(msg_step).or_default();
match voters_list.get(signer.bytes()) {
None => voters_list.insert(*signer.bytes(), v.clone()),
Some(prev_vote) => {
return Err(AggregatorError::ConflictingVote(
prev_vote.clone(),
))
}
};
}

// Aggregate Signatures
aggr_sign.add(signature)?;
Expand All @@ -134,6 +150,8 @@ impl<V: StepVote> Aggregator<V> {
event = "vote aggregated",
?vote,
from = signer.to_bs58(),
iter = v.header().iteration,
step = ?V::STEP_NAME,
added,
total,
majority = committee.majority_quorum(),
Expand All @@ -158,6 +176,8 @@ impl<V: StepVote> Aggregator<V> {
tracing::info!(
event = "quorum reached",
?vote,
iter = v.header().iteration,
step = ?V::STEP_NAME,
total,
target = quorum_target,
bitset,
Expand Down
7 changes: 5 additions & 2 deletions consensus/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::commons::{ConsensusError, Database, QuorumMsgSender, RoundUpdate};
use crate::config::CONSENSUS_MAX_ITER;
use crate::config::{CONSENSUS_MAX_ITER, EMERGENCY_MODE_ITERATION_THRESHOLD};
use crate::operations::Operations;
use crate::phase::Phase;

Expand All @@ -20,9 +20,9 @@ use tracing::{debug, error, info, Instrument};

use crate::iteration_ctx::IterationCtx;
use crate::step_votes_reg::AttInfoRegistry;
use std::env;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{cmp, env};
use tokio::sync::{oneshot, Mutex};
use tokio::task::JoinHandle;

Expand Down Expand Up @@ -187,6 +187,9 @@ impl<T: Operations + 'static, D: Database + 'static> Consensus<T, D> {
let (prev_block_hash, saved_iter) =
db.lock().await.get_last_iter().await;

let saved_iter =
cmp::min(EMERGENCY_MODE_ITERATION_THRESHOLD, saved_iter);

if ru.hash() == prev_block_hash {
// If starting from `saved_iter`, we regenerate all committees
// in case they are needed to process past-iteration messages in
Expand Down
12 changes: 7 additions & 5 deletions consensus/src/execution_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,13 @@ impl<'a, T: Operations + 'static> ExecutionCtx<'a, T> {
}

Payload::ValidationResult(validation_result) => {
self.try_cast_ratification_vote(
msg_iteration,
validation_result,
)
.await
if let QuorumType::Valid = validation_result.quorum() {
self.try_cast_ratification_vote(
msg_iteration,
validation_result,
)
.await
}
}
_ => {
// Not supported.
Expand Down
2 changes: 1 addition & 1 deletion consensus/src/ratification/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl MsgHandler for RatificationHandler {
event = "Cannot collect vote",
?error,
from = p.sign_info().signer.to_bs58(),
?p.vote,
vote = ?p.vote,
msg_step = p.get_step(),
msg_round = p.header().round,
);
Expand Down
15 changes: 10 additions & 5 deletions consensus/src/ratification/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::commons::{ConsensusError, RoundUpdate};
use crate::config::EMERGENCY_MODE_ITERATION_THRESHOLD;
use crate::execution_ctx::ExecutionCtx;
use crate::operations::Operations;

use crate::msg_handler::{HandleMsgOutput, MsgHandler};
use crate::ratification::handler;
use node_data::message::payload::{self, ValidationResult};
use node_data::message::payload::{self, QuorumType, ValidationResult};
use node_data::message::{AsyncQueue, Message, Payload, StepMessage};
use node_data::{get_current_timestamp, message};
use std::sync::Arc;
Expand All @@ -35,11 +36,15 @@ impl RatificationStep {

let msg = Message::from(ratification);

// Publish ratification vote
info!(event = "send_vote", validation_bitset = result.sv().bitset);
if result.quorum() == QuorumType::Valid
|| iteration < EMERGENCY_MODE_ITERATION_THRESHOLD
{
// Publish ratification vote
info!(event = "send_vote", validation_bitset = result.sv().bitset);

// Publish
outbound.try_send(msg.clone());
// Publish
outbound.try_send(msg.clone());
}

msg
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/src/validation/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl MsgHandler for ValidationHandler {
event = "Cannot collect vote",
?error,
from = p.sign_info().signer.to_bs58(),
?p.vote,
vote = ?p.vote,
msg_step = p.get_step(),
msg_round = p.header().round,
);
Expand Down
12 changes: 7 additions & 5 deletions consensus/src/validation/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::commons::{ConsensusError, RoundUpdate};
use crate::config;
use crate::config::{self, EMERGENCY_MODE_ITERATION_THRESHOLD};
use crate::execution_ctx::ExecutionCtx;
use crate::operations::{Operations, Voter};
use crate::validation::handler;
Expand Down Expand Up @@ -126,11 +126,13 @@ impl<T: Operations + 'static> ValidationStep<T> {
info!(event = "send_vote", vote = ?validation.vote);
let msg = Message::from(validation);

// Publish
outbound.try_send(msg.clone());
if vote.is_valid() || iteration < EMERGENCY_MODE_ITERATION_THRESHOLD {
// Publish
outbound.try_send(msg.clone());

// Register my vote locally
inbound.try_send(msg);
// Register my vote locally
inbound.try_send(msg);
}
}

async fn call_vst(
Expand Down
2 changes: 2 additions & 0 deletions node-data/src/ledger/faults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub enum InvalidFault {
PrevHashMismatch,
#[error("Iteration mismatch")]
IterationMismatch,
#[error("Faults related to emergency iteration")]
EmergencyIteration,
#[error("Round mismatch")]
RoundMismatch,
#[error("Invalid Signature {0}")]
Expand Down
10 changes: 5 additions & 5 deletions node-data/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@ pub mod payload {
}

impl Vote {
pub fn is_valid(&self) -> bool {
matches!(self, Vote::Valid(_))
}
pub fn size(&self) -> usize {
const ENUM_BYTE: usize = 1;

Expand Down Expand Up @@ -654,11 +657,8 @@ pub mod payload {
})
}
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(
any(feature = "faker", test),
derive(fake::Dummy, Eq, PartialEq)
)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
pub enum QuorumType {
/// Supermajority of Valid votes
Valid = 0,
Expand Down
8 changes: 7 additions & 1 deletion node/src/chain/header_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::database;
use crate::database::Ledger;
use anyhow::anyhow;
use dusk_bytes::Serializable;
use dusk_consensus::config::{MINIMUM_BLOCK_TIME, RELAX_ITERATION_THRESHOLD};
use dusk_consensus::config::{
EMERGENCY_MODE_ITERATION_THRESHOLD, MINIMUM_BLOCK_TIME,
RELAX_ITERATION_THRESHOLD,
};
use dusk_consensus::operations::Voter;
use dusk_consensus::quorum::verifiers;
use dusk_consensus::quorum::verifiers::QuorumResult;
Expand Down Expand Up @@ -297,6 +300,9 @@ pub async fn verify_faults<DB: database::DB>(
) -> Result<(), InvalidFault> {
for f in faults {
let fault_header = f.validate(current_height)?;
if fault_header.iteration >= EMERGENCY_MODE_ITERATION_THRESHOLD {
return Err(InvalidFault::EmergencyIteration);
}
db.read()
.await
.view(|db| {
Expand Down

0 comments on commit 8dbdd84

Please sign in to comment.