Skip to content

Commit

Permalink
Merge pull request #2004 from dusk-network/refactor_verify_att
Browse files Browse the repository at this point in the history
Refactor attestation verification
  • Loading branch information
fed-franz authored Jul 29, 2024
2 parents 597ad87 + abbc821 commit 96eab99
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 199 deletions.
8 changes: 4 additions & 4 deletions consensus/src/commons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use node_data::message::{AsyncQueue, Message, Payload};
use node_data::StepName;
use tracing::error;

use crate::operations::VoterWithCredits;
use crate::operations::Voter;

pub type TimeoutSet = HashMap<StepName, Duration>;

Expand All @@ -36,7 +36,7 @@ pub struct RoundUpdate {
seed: Seed,
hash: [u8; 32],
att: Attestation,
att_voters: Vec<VoterWithCredits>,
att_voters: Vec<Voter>,
timestamp: u64,

pub base_timeouts: TimeoutSet,
Expand All @@ -48,7 +48,7 @@ impl RoundUpdate {
secret_key: BlsSecretKey,
tip_header: &Header,
base_timeouts: TimeoutSet,
att_voters: Vec<VoterWithCredits>,
att_voters: Vec<Voter>,
) -> Self {
let round = tip_header.height + 1;
RoundUpdate {
Expand Down Expand Up @@ -80,7 +80,7 @@ impl RoundUpdate {
self.timestamp
}

pub fn att_voters(&self) -> &Vec<VoterWithCredits> {
pub fn att_voters(&self) -> &Vec<Voter> {
&self.att_voters
}
}
Expand Down
10 changes: 5 additions & 5 deletions consensus/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::fmt;
use std::io;
use std::time::Duration;

use execution_core::BlsPublicKey;
use node_data::bls::PublicKey;
use node_data::ledger::{
Block, Fault, Header, InvalidFault, Slash, SpentTransaction, Transaction,
};
Expand All @@ -17,7 +17,7 @@ use thiserror::Error;

pub type StateRoot = [u8; 32];
pub type EventHash = [u8; 32];
pub type VoterWithCredits = (BlsPublicKey, usize);
pub type Voter = (PublicKey, usize);

#[derive(Debug, Error)]
pub enum Error {
Expand Down Expand Up @@ -53,7 +53,7 @@ pub struct CallParams {
pub block_gas_limit: u64,
pub generator_pubkey: node_data::bls::PublicKey,
pub to_slash: Vec<Slash>,
pub voters_pubkey: Option<Vec<VoterWithCredits>>,
pub voters_pubkey: Option<Vec<Voter>>,
}

#[derive(Default)]
Expand Down Expand Up @@ -86,7 +86,7 @@ pub trait Operations: Send + Sync {
&self,
candidate_header: &Header,
disable_winning_att_check: bool,
) -> Result<(u8, Vec<VoterWithCredits>, Vec<VoterWithCredits>), Error>;
) -> Result<(u8, Vec<Voter>, Vec<Voter>), Error>;

async fn verify_faults(
&self,
Expand All @@ -97,7 +97,7 @@ pub trait Operations: Send + Sync {
async fn verify_state_transition(
&self,
blk: &Block,
voters: &[VoterWithCredits],
voters: &[Voter],
) -> Result<VerificationOutput, Error>;

async fn execute_state_transition(
Expand Down
4 changes: 2 additions & 2 deletions consensus/src/proposal/block_generator.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::{get_current_timestamp, RoundUpdate};
use crate::operations::{CallParams, Operations, VoterWithCredits};
use crate::operations::{CallParams, Operations, Voter};
use node_data::ledger::{
to_str, Attestation, Block, Fault, IterationsInfo, Seed, Slash,
};
Expand Down Expand Up @@ -90,7 +90,7 @@ impl<T: Operations> Generator<T> {
iteration: u8,
failed_iterations: IterationsInfo,
faults: &[Fault],
voters: &[VoterWithCredits],
voters: &[Voter],
) -> Result<Block, crate::operations::Error> {
let to_slash =
Slash::from_iterations_and_faults(&failed_iterations, faults)?;
Expand Down
127 changes: 73 additions & 54 deletions consensus/src/quorum/verifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@

use node_data::bls::PublicKey;
use node_data::ledger::{Seed, StepVotes};
use node_data::message::payload::{self, Quorum, Vote};
use node_data::message::payload::{self, Vote};
use node_data::message::{ConsensusHeader, StepMessage};
use node_data::{Serializable, StepName};

use crate::commons::StepSigError;
use crate::operations::Voter;
use crate::user::cluster::Cluster;
use crate::user::committee::{Committee, CommitteeSet};
use crate::user::sortition;
Expand All @@ -19,54 +20,6 @@ use crate::config::CONSENSUS_MAX_ITER;
use dusk_bytes::Serializable as BytesSerializable;
use execution_core::{BlsAggPublicKey, BlsSignature};
use tokio::sync::RwLock;
use tracing::error;

/// Performs all three-steps verification of a quorum msg.
pub async fn verify_quorum(
quorum: &Quorum,
committees_set: &RwLock<CommitteeSet<'_>>,
seed: Seed,
) -> Result<(), StepSigError> {
// Verify validation
verify_step_votes(
&quorum.header,
quorum.vote(),
&quorum.att.validation,
committees_set,
seed,
StepName::Validation,
)
.await
.map_err(|e| {
error!(
desc = "invalid validation",
sv = ?quorum.att.validation,
hdr = ?quorum.header,
);
e
})?;

// Verify ratification
verify_step_votes(
&quorum.header,
quorum.vote(),
&quorum.att.ratification,
committees_set,
seed,
StepName::Ratification,
)
.await
.map_err(|e| {
error!(
desc = "invalid ratification",
sv = ?quorum.att.ratification,
hdr = ?quorum.header,
);
e
})?;

Ok(())
}

pub async fn verify_step_votes(
header: &ConsensusHeader,
Expand All @@ -75,7 +28,7 @@ pub async fn verify_step_votes(
committees_set: &RwLock<CommitteeSet<'_>>,
seed: Seed,
step: StepName,
) -> Result<(QuorumResult, Committee), StepSigError> {
) -> Result<(QuorumResult, Vec<Voter>), StepSigError> {
let round = header.round;
let iteration = header.iteration;

Expand Down Expand Up @@ -108,8 +61,9 @@ pub async fn verify_step_votes(
let set = committees_set.read().await;
let committee = set.get(&cfg).expect("committee to be created");

let quorum_result = verify_votes(header, step, vote, sv, committee)?;
Ok((quorum_result, committee.clone()))
let (quorum_result, voters) =
verify_votes(header, step, vote, sv, committee)?;
Ok((quorum_result, voters))
}

#[derive(Default)]
Expand All @@ -130,7 +84,7 @@ pub fn verify_votes(
vote: &Vote,
step_votes: &StepVotes,
committee: &Committee,
) -> Result<QuorumResult, StepSigError> {
) -> Result<(QuorumResult, Vec<Voter>), StepSigError> {
let bitset = step_votes.bitset;
let signature = step_votes.aggregate_signature().inner();
let sub_committee = committee.intersect(bitset);
Expand Down Expand Up @@ -173,7 +127,7 @@ pub fn verify_votes(
verify_step_signature(header, step, vote, apk, signature)?;
}
// Verification done
Ok(quorum_result)
Ok((quorum_result, sub_committee.to_voters()))
}

impl Cluster<PublicKey> {
Expand All @@ -190,6 +144,10 @@ impl Cluster<PublicKey> {
None => Err(StepSigError::EmptyApk),
}
}

pub fn to_voters(self) -> Vec<Voter> {
self.into_vec()
}
}

fn verify_step_signature(
Expand All @@ -213,3 +171,64 @@ fn verify_step_signature(
apk.verify(&sig, &msg)?;
Ok(())
}

pub async fn get_step_voters(
header: &ConsensusHeader,
sv: &StepVotes,
committees_set: &RwLock<CommitteeSet<'_>>,
seed: Seed,
step: StepName,
) -> Vec<Voter> {
// compute committee for `step`
let committee =
get_step_committee(header, committees_set, seed, step).await;

// extract quorum voters from `sv`
let bitset = sv.bitset;
let q_committee = committee.intersect(bitset);

q_committee.to_voters()
}

async fn get_step_committee(
header: &ConsensusHeader,
committees_set: &RwLock<CommitteeSet<'_>>,
seed: Seed,
step: StepName,
) -> Committee {
let round = header.round;
let iteration = header.iteration;

// exclude current-iteration generator
let mut exclusion_list = vec![];
let generator = committees_set
.read()
.await
.provisioners()
.get_generator(iteration, seed, round);

exclusion_list.push(generator);

// exclude next-iteration generator
if iteration < CONSENSUS_MAX_ITER {
let next_generator = committees_set
.read()
.await
.provisioners()
.get_generator(iteration + 1, seed, round);

exclusion_list.push(next_generator);
}

let cfg =
sortition::Config::new(seed, round, iteration, step, exclusion_list);

if committees_set.read().await.get(&cfg).is_none() {
let _ = committees_set.write().await.get_or_create(&cfg);
}

let set = committees_set.read().await;
let committee = set.get(&cfg).expect("committee to be created");

committee.clone()
}
4 changes: 4 additions & 0 deletions consensus/src/user/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ where
self.0.iter()
}

pub fn into_vec(self) -> Vec<(T, usize)> {
self.0.into_iter().collect()
}

pub fn contains_key(&self, key: &T) -> bool {
self.0.contains_key(key)
}
Expand Down
4 changes: 2 additions & 2 deletions consensus/src/validation/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::commons::{ConsensusError, Database, RoundUpdate};
use crate::config;
use crate::execution_ctx::ExecutionCtx;
use crate::operations::{Operations, VoterWithCredits};
use crate::operations::{Operations, Voter};
use crate::validation::handler;
use anyhow::anyhow;
use node_data::ledger::{to_str, Block};
Expand Down Expand Up @@ -140,7 +140,7 @@ impl<T: Operations + 'static> ValidationStep<T> {

async fn call_vst(
candidate: &Block,
voters: &[VoterWithCredits],
voters: &[Voter],
executor: &Arc<T>,
) -> anyhow::Result<()> {
match executor.verify_state_transition(candidate, voters).await {
Expand Down
11 changes: 11 additions & 0 deletions node-data/src/ledger/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::message::ConsensusHeader;

use super::*;

pub type Seed = Signature;
Expand Down Expand Up @@ -58,6 +60,15 @@ impl std::fmt::Debug for Header {
}

impl Header {
/// Return the corresponding ConsensusHeader
pub fn to_consensus_header(&self) -> ConsensusHeader {
ConsensusHeader {
prev_block_hash: self.prev_block_hash,
round: self.height,
iteration: self.iteration,
}
}

/// Marshal hashable fields.
pub(crate) fn marshal_hashable<W: Write>(
&self,
Expand Down
26 changes: 17 additions & 9 deletions node/benches/accept.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use node_data::ledger::{Attestation, StepVotes};
use node_data::message::payload::{
QuorumType, RatificationResult, ValidationResult, Vote,
};
use node_data::message::ConsensusHeader;
use node_data::{ledger, StepName};
use rand::rngs::StdRng;
use rand::SeedableRng;
Expand Down Expand Up @@ -105,8 +106,8 @@ where
r
}

pub fn verify_block_att(c: &mut Criterion) {
with_group("verify_block_att", c, |group| {
pub fn verify_att(c: &mut Criterion) {
with_group("verify_att", c, |group| {
for input in INPUTS {
group.measurement_time(Duration::from_secs(input.measurement_time));
let mut keys = vec![];
Expand Down Expand Up @@ -151,18 +152,25 @@ pub fn verify_block_att(c: &mut Criterion) {

group.bench_function(
BenchmarkId::new(
"verify_block_att",
"verify_att",
format!("{} prov", input.provisioners),
),
move |b| {
b.to_async(FuturesExecutor).iter(|| async {
chain::verify_block_att(
[0u8; 32],
let consensus_header = ConsensusHeader {
prev_block_hash: [0u8; 32],
round: tip_header.height + 1,
iteration: 0,
};

chain::verify_att(
&att,
consensus_header,
tip_header.seed,
&provisioners,
tip_header.height + 1,
&att,
iteration,
RatificationResult::Success(Vote::Valid(
block_hash,
)),
)
.await
.expect("block to be verified")
Expand Down Expand Up @@ -200,5 +208,5 @@ const INPUTS: &[Input] = &[
measurement_time: 15,
},
];
criterion_group!(benches, verify_block_att);
criterion_group!(benches, verify_att);
criterion_main!(benches);
Loading

0 comments on commit 96eab99

Please sign in to comment.