Skip to content

Commit

Permalink
Merge pull request #2140 from dusk-network/fix-2122
Browse files Browse the repository at this point in the history
consensus: Limit transactions & faults in proposed block
  • Loading branch information
fed-franz authored Sep 7, 2024
2 parents 4ce881d + 6938202 commit 004e58e
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 3 deletions.
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;
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 @@ -135,6 +135,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

0 comments on commit 004e58e

Please sign in to comment.