Skip to content

Commit

Permalink
Merge pull request #1161 from dusk-network/bench_verify_block
Browse files Browse the repository at this point in the history
  • Loading branch information
herr-seppia authored Dec 1, 2023
2 parents 5ae8540 + 06b7c2a commit 1f59b9f
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 98 deletions.
8 changes: 4 additions & 4 deletions consensus/src/agreement/verifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,13 @@ pub async fn verify_votes(

impl Cluster<PublicKey> {
fn aggregate_pks(&self) -> Result<dusk_bls12_381_sign::APK, Error> {
let pks: Vec<&dusk_bls12_381_sign::PublicKey> =
self.iter().map(|(pubkey, _)| pubkey.inner()).collect();
let pks: Vec<_> =
self.iter().map(|(pubkey, _)| *pubkey.inner()).collect();

match pks.split_first() {
Some((&first, rest)) => {
Some((first, rest)) => {
let mut apk = dusk_bls12_381_sign::APK::from(first);
rest.iter().for_each(|&&p| apk.aggregate(&[p]));
apk.aggregate(rest);
Ok(apk)
}
None => Err(Error::EmptyApk),
Expand Down
2 changes: 1 addition & 1 deletion consensus/src/user/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use std::collections::btree_map::Iter;
use std::collections::BTreeMap;

#[derive(Debug)]
#[derive(Debug, Default)]
pub struct Cluster<T>(BTreeMap<T, usize>);

impl<T> Cluster<T>
Expand Down
11 changes: 3 additions & 8 deletions consensus/src/user/committee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,9 @@ pub struct Committee {
cfg: sortition::Config,
}

impl Iterator for Committee {
type Item = PublicKey;

fn next(&mut self) -> Option<Self::Item> {
self.members
.iter()
.next()
.map(|(public_key, _)| public_key.clone())
impl Committee {
pub fn iter(&self) -> impl Iterator<Item = &PublicKey> {
self.members.keys()
}
}

Expand Down
2 changes: 1 addition & 1 deletion consensus/src/user/provisioners.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl Provisioners {
/// committee members for a given round, step and seed.
///
/// Returns a vector of provisioners public keys.
pub fn create_committee(
pub(crate) fn create_committee(
&mut self,
cfg: &sortition::Config,
) -> Vec<PublicKey> {
Expand Down
6 changes: 6 additions & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@ node-data = { version = "0.1", path = "../node-data", features = ["faker"] }
rand = "0.8"
rand_core = "0.6"
tempdir = "0.3"
criterion = { version = "0.5", features = ["async_futures"] }

[build-dependencies]
rustc_tools_util = "=0.2.0"

[features]
with_telemetry = ["dep:console-subscriber"]


[[bench]]
name = "accept"
harness = false
176 changes: 176 additions & 0 deletions node/benches/accept.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use std::time::Duration;

use node::chain;

use criterion::async_executor::FuturesExecutor;
use criterion::measurement::WallTime;
use criterion::{
criterion_group, criterion_main, BenchmarkGroup, BenchmarkId, Criterion,
};

use dusk_bls12_381_sign::{
PublicKey as BlsPublicKey, SecretKey as BlsSecretKey,
Signature as BlsSignature,
};
use dusk_bytes::Serializable;
use dusk_consensus::user::{
cluster::Cluster, committee::Committee, provisioners::Provisioners,
sortition::Config as SortitionConfig,
};
use node_data::{
bls::PublicKey,
ledger::{Certificate, Signature, StepVotes},
message,
};
use rand::rngs::StdRng;
use rand::SeedableRng;

fn create_step_votes(
seed: Signature,
round: u64,
block_hash: [u8; 32],
step: u8,
iteration: u8,
provisioners: Provisioners,
keys: &[(PublicKey, BlsSecretKey)],
) -> StepVotes {
let sortition_config =
SortitionConfig::new(seed, round, iteration * 3 + step, 64);

let committee = Committee::new(
PublicKey::default(),
&mut provisioners.clone(),
sortition_config,
);

let hdr = message::Header {
round,
step: step % 3,
block_hash,
..Default::default()
};
let mut signatures = vec![];
let mut cluster = Cluster::<PublicKey>::default();
for (pk, sk) in keys.iter() {
if let Some(weight) = committee.votes_for(pk) {
let sig = hdr.sign(sk, pk.inner());
signatures.push(BlsSignature::from_bytes(&sig).unwrap());
cluster.set_weight(pk, weight);
}
}

let bitset = committee.bits(&cluster);

let (first, rest) = signatures.split_first().unwrap();
let aggregate_signature = first.aggregate(rest).to_bytes();
StepVotes::new(aggregate_signature, bitset)
}

pub fn with_group<T, F>(name: &str, c: &mut Criterion, closure: F) -> T
where
F: FnOnce(&mut BenchmarkGroup<WallTime>) -> T,
{
let mut group = c.benchmark_group(name);
let r = closure(&mut group);
group.finish();
r
}

pub fn verify_block_cert(c: &mut Criterion) {
with_group("verify_block_cert", c, |group| {
for input in INPUTS {
group.measurement_time(Duration::from_secs(input.measurement_time));
let mut keys = vec![];
let mut provisioners = Provisioners::new();
let rng = &mut StdRng::seed_from_u64(0xbeef);
for _ in 0..input.provisioners {
let sk = BlsSecretKey::random(rng);
let pk = BlsPublicKey::from(&sk);
let pk = PublicKey::new(pk);
keys.push((pk.clone(), sk));
provisioners.add_member_with_value(pk, 1000000000000)
}
let height = 1;
let seed = Signature([5; 48]);
let block_hash = [1; 32];
let curr_public_key = keys.first().unwrap().0.clone();
let iteration = 0;
let mut cert = Certificate::default();

cert.first_reduction = create_step_votes(
seed,
height,
block_hash,
1,
iteration,
provisioners.clone(),
&keys[..],
);
cert.second_reduction = create_step_votes(
seed,
height,
block_hash,
2,
iteration,
provisioners.clone(),
&keys[..],
);
group.bench_function(
BenchmarkId::new(
"verify_block_cert",
format!("{} prov", input.provisioners),
),
move |b| {
b.to_async(FuturesExecutor).iter(|| {
chain::verify_block_cert(
seed,
&provisioners,
&curr_public_key,
block_hash,
height,
&cert,
iteration,
true,
)
})
},
);
}
})
}

struct Input {
provisioners: usize,
measurement_time: u64, // secs
}

const INPUTS: &[Input] = &[
Input {
provisioners: 1,
measurement_time: 10,
},
Input {
provisioners: 30,
measurement_time: 10,
},
Input {
provisioners: 64,
measurement_time: 10,
},
Input {
provisioners: 256,
measurement_time: 15,
},
Input {
provisioners: 1000,
measurement_time: 15,
},
];
criterion_group!(benches, verify_block_cert);
criterion_main!(benches);
2 changes: 2 additions & 0 deletions node/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ use self::acceptor::{Acceptor, RevertTarget};
use self::consensus::Task;
use self::fsm::SimpleFSM;

pub use acceptor::verify_block_cert;

const TOPICS: &[u8] = &[
Topics::Block as u8,
Topics::NewBlock as u8,
Expand Down
29 changes: 17 additions & 12 deletions node/src/chain/acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use dusk_consensus::consensus::{self, Consensus};
use dusk_consensus::contract_state::{
CallParams, Error, Operations, Output, StateRoot,
};
use dusk_consensus::user::committee::CommitteeSet;
use dusk_consensus::user::committee::{Committee, CommitteeSet};
use dusk_consensus::user::provisioners::Provisioners;
use dusk_consensus::user::sortition;
use hex::ToHex;
Expand Down Expand Up @@ -190,22 +190,27 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
return;
}
let mut prov = provisioners_list.clone();
prov.update_eligibility_flag(round);
for iter in 0..iteration {
let committee_keys = prov.create_committee(&sortition::Config {
committee_size: SELECTION_COMMITTEE_SIZE,
round,
seed,
step: iter * 3,
});
if committee_keys.len() != 1 {
let len = committee_keys.len();
let committee_keys = Committee::new(
node_data::bls::PublicKey::default(),
&mut prov,
sortition::Config {
committee_size: SELECTION_COMMITTEE_SIZE,
round,
seed,
step: iter * 3,
},
);

if committee_keys.size() != 1 {
let len = committee_keys.size();
error!(
"Unable to generate voting committee for missed block: {len}",
)
} else {
let generator = committee_keys
.first()
.iter()
.next()
.expect("committee to have 1 entry")
.to_bs58();
warn!(
Expand Down Expand Up @@ -553,7 +558,7 @@ pub(crate) async fn verify_block_header<DB: database::DB>(
}

#[allow(clippy::too_many_arguments)]
async fn verify_block_cert(
pub async fn verify_block_cert(
curr_seed: Signature,
curr_eligible_provisioners: &Provisioners,
curr_public_key: &node_data::bls::PublicKey,
Expand Down
Loading

0 comments on commit 1f59b9f

Please sign in to comment.