Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consensus: Limit transactions & faults in proposed block #2140

Merged
merged 6 commits into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
base64 = "0.13"
node-data = { version = "0.1", path = "../node-data", features = ["faker"]}
criterion = "0.5"

[[bench]]
name = "merkle"
harness = false
34 changes: 34 additions & 0 deletions consensus/benches/merkle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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 criterion::{criterion_group, criterion_main, Criterion};
use dusk_consensus::config::MAX_NUMBER_OF_TRANSACTIONS;
use dusk_consensus::merkle::merkle_root;
use rand::rngs::StdRng;
use rand::RngCore;
use rand::SeedableRng;

fn merkle(c: &mut Criterion) {
let tx_hashes: Vec<_> = (0..MAX_NUMBER_OF_TRANSACTIONS)
.map(|seed| {
let rng = &mut StdRng::seed_from_u64(seed as u64);
let mut buf = [0u8; 32];
rng.fill_bytes(&mut buf);
buf
})
.collect();

let label: String = format!("merkle_{}", MAX_NUMBER_OF_TRANSACTIONS);

c.bench_function(&label, |b| {
b.iter(|| {
let _ = merkle_root(&tx_hashes[..]);
})
});
}

criterion_group!(benches, merkle);
criterion_main!(benches);
2 changes: 2 additions & 0 deletions consensus/src/commons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub enum ConsensusError {
ChildTaskTerminated,
Canceled(u64),
VoteAlreadyCollected,
TooManyTransactions(usize),
TooManyFaults(usize),
}

impl From<StepSigError> for ConsensusError {
Expand Down
2 changes: 2 additions & 0 deletions consensus/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub const VALIDATION_COMMITTEE_CREDITS: usize = 64;
pub const RATIFICATION_COMMITTEE_CREDITS: usize = 64;

pub const RELAX_ITERATION_THRESHOLD: u8 = 8;
pub const MAX_NUMBER_OF_TRANSACTIONS: usize = 1_000;
pub const MAX_NUMBER_OF_FAULTS: usize = 100;

/// Emergency mode is enabled after 16 iterations
pub const EMERGENCY_MODE_ITERATION_THRESHOLD: u8 = 16;
Expand Down
9 changes: 8 additions & 1 deletion consensus/src/proposal/block_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::cmp::max;

use crate::merkle::merkle_root;

use crate::config::MINIMUM_BLOCK_TIME;
use crate::config::{MAX_NUMBER_OF_FAULTS, MINIMUM_BLOCK_TIME};
use dusk_bytes::Serializable;
use node_data::message::payload::Candidate;
use node_data::message::{ConsensusHeader, Message, SignInfo, StepMessage};
Expand Down Expand Up @@ -92,6 +92,13 @@ impl<T: Operations> Generator<T> {
faults: &[Fault],
voters: &[Voter],
) -> Result<Block, crate::operations::Error> {
// Limit number of faults in the block
let faults = if faults.len() > MAX_NUMBER_OF_FAULTS {
&faults[..MAX_NUMBER_OF_FAULTS]
} else {
faults
};

let to_slash =
Slash::from_iterations_and_faults(&failed_iterations, faults)?;

Expand Down
13 changes: 13 additions & 0 deletions consensus/src/proposal/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use crate::commons::{ConsensusError, Database, RoundUpdate};
use crate::config::{MAX_NUMBER_OF_FAULTS, MAX_NUMBER_OF_TRANSACTIONS};
use crate::merkle::merkle_root;
use crate::msg_handler::{HandleMsgOutput, MsgHandler};
use crate::user::committee::Committee;
Expand Down Expand Up @@ -95,13 +96,25 @@ impl<D: Database> ProposalHandler<D> {
return Err(ConsensusError::InvalidBlockHash);
}

if p.candidate.txs().len() > MAX_NUMBER_OF_TRANSACTIONS {
return Err(ConsensusError::TooManyTransactions(
p.candidate.txs().len(),
));
}

let tx_hashes: Vec<_> =
p.candidate.txs().iter().map(|t| t.hash()).collect();
let tx_root = merkle_root(&tx_hashes[..]);
if tx_root != p.candidate.header().txroot {
return Err(ConsensusError::InvalidBlock);
}

if p.candidate.faults().len() > MAX_NUMBER_OF_FAULTS {
return Err(ConsensusError::TooManyFaults(
p.candidate.faults().len(),
));
}

let fault_hashes: Vec<_> =
p.candidate.faults().iter().map(|t| t.hash()).collect();
let fault_root = merkle_root(&fault_hashes[..]);
Expand Down
11 changes: 9 additions & 2 deletions rusk/src/lib/node/rusk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use tracing::{debug, info, warn};
use dusk_bytes::{DeserializableSlice, Serializable};
use dusk_consensus::config::{
ratification_extra, ratification_quorum, validation_extra,
validation_quorum, RATIFICATION_COMMITTEE_CREDITS,
VALIDATION_COMMITTEE_CREDITS,
validation_quorum, MAX_NUMBER_OF_TRANSACTIONS,
RATIFICATION_COMMITTEE_CREDITS, VALIDATION_COMMITTEE_CREDITS,
};
use dusk_consensus::operations::{CallParams, VerificationOutput, Voter};
use execution_core::{
Expand Down Expand Up @@ -131,6 +131,13 @@ impl Rusk {
break;
}
}

// Limit execution to the block transactions limit
if spent_txs.len() >= MAX_NUMBER_OF_TRANSACTIONS {
info!("Maximum number of transactions reached");
break;
}

let tx_id = hex::encode(unspent_tx.id());
if unspent_tx.inner.gas_limit() > block_gas_left {
info!("Skipping {tx_id} due gas_limit greater than left: {block_gas_left}");
Expand Down
Loading