From 30bad4a5d320b051217f44646e65181d70b06a51 Mon Sep 17 00:00:00 2001 From: Goshawk Date: Fri, 16 Aug 2024 13:19:00 +0300 Subject: [PATCH 1/6] consensus: Bench merkle_root calculation --- consensus/benches/merkle.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 consensus/benches/merkle.rs diff --git a/consensus/benches/merkle.rs b/consensus/benches/merkle.rs new file mode 100644 index 0000000000..35463e3c43 --- /dev/null +++ b/consensus/benches/merkle.rs @@ -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); From b3d588b6411e6a21f2267968741607d0e6126278 Mon Sep 17 00:00:00 2001 From: Goshawk Date: Fri, 16 Aug 2024 13:20:17 +0300 Subject: [PATCH 2/6] consensus: Reject candidates with txs count higher than MAX_NUMBER_OF_TRANSACTIONS --- consensus/Cargo.toml | 5 +++++ consensus/src/commons.rs | 1 + consensus/src/config.rs | 1 + consensus/src/proposal/handler.rs | 7 +++++++ 4 files changed, 14 insertions(+) diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml index b03d11f09a..dbeb83a953 100644 --- a/consensus/Cargo.toml +++ b/consensus/Cargo.toml @@ -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 \ No newline at end of file diff --git a/consensus/src/commons.rs b/consensus/src/commons.rs index 558d5aa63e..3421e55b7f 100644 --- a/consensus/src/commons.rs +++ b/consensus/src/commons.rs @@ -123,6 +123,7 @@ pub enum ConsensusError { ChildTaskTerminated, Canceled(u64), VoteAlreadyCollected, + TooManyTransactions(usize), } impl From for ConsensusError { diff --git a/consensus/src/config.rs b/consensus/src/config.rs index f93322aedf..569c2d7aa0 100644 --- a/consensus/src/config.rs +++ b/consensus/src/config.rs @@ -15,6 +15,7 @@ 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 = 30_000; /// Emergency mode is enabled after 16 iterations pub const EMERGENCY_MODE_ITERATION_THRESHOLD: u8 = 16; diff --git a/consensus/src/proposal/handler.rs b/consensus/src/proposal/handler.rs index 7d2500a3cc..5cd76f701c 100644 --- a/consensus/src/proposal/handler.rs +++ b/consensus/src/proposal/handler.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::commons::{ConsensusError, Database, RoundUpdate}; +use crate::config::MAX_NUMBER_OF_TRANSACTIONS; use crate::merkle::merkle_root; use crate::msg_handler::{HandleMsgOutput, MsgHandler}; use crate::user::committee::Committee; @@ -95,6 +96,12 @@ impl ProposalHandler { 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[..]); From f1d7d47eda218b475ecdd9e6ee053073a153121a Mon Sep 17 00:00:00 2001 From: Federico Franzoni <8609060+fed-franz@users.noreply.github.com> Date: Fri, 6 Sep 2024 12:20:35 +0200 Subject: [PATCH 3/6] consensus: reduce max number of transactions --- consensus/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/src/config.rs b/consensus/src/config.rs index 569c2d7aa0..1203cb3930 100644 --- a/consensus/src/config.rs +++ b/consensus/src/config.rs @@ -15,7 +15,7 @@ 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 = 30_000; +pub const MAX_NUMBER_OF_TRANSACTIONS: usize = 1_000; /// Emergency mode is enabled after 16 iterations pub const EMERGENCY_MODE_ITERATION_THRESHOLD: u8 = 16; From c9e058b4129225bdbe7e9bc871ecd59d13e1da47 Mon Sep 17 00:00:00 2001 From: Federico Franzoni <8609060+fed-franz@users.noreply.github.com> Date: Fri, 6 Sep 2024 12:36:44 +0200 Subject: [PATCH 4/6] consensus: introduce max number of faults --- consensus/src/commons.rs | 1 + consensus/src/config.rs | 1 + consensus/src/proposal/handler.rs | 10 ++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/consensus/src/commons.rs b/consensus/src/commons.rs index 3421e55b7f..c73bd0dbea 100644 --- a/consensus/src/commons.rs +++ b/consensus/src/commons.rs @@ -124,6 +124,7 @@ pub enum ConsensusError { Canceled(u64), VoteAlreadyCollected, TooManyTransactions(usize), + TooManyFaults(usize), } impl From for ConsensusError { diff --git a/consensus/src/config.rs b/consensus/src/config.rs index 1203cb3930..763fbd0890 100644 --- a/consensus/src/config.rs +++ b/consensus/src/config.rs @@ -16,6 +16,7 @@ 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; diff --git a/consensus/src/proposal/handler.rs b/consensus/src/proposal/handler.rs index 5cd76f701c..96686b69fe 100644 --- a/consensus/src/proposal/handler.rs +++ b/consensus/src/proposal/handler.rs @@ -5,7 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::commons::{ConsensusError, Database, RoundUpdate}; -use crate::config::MAX_NUMBER_OF_TRANSACTIONS; +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; @@ -96,7 +96,7 @@ impl ProposalHandler { return Err(ConsensusError::InvalidBlockHash); } - if p.candidate.txs().len() >= MAX_NUMBER_OF_TRANSACTIONS { + if p.candidate.txs().len() > MAX_NUMBER_OF_TRANSACTIONS { return Err(ConsensusError::TooManyTransactions( p.candidate.txs().len(), )); @@ -109,6 +109,12 @@ impl ProposalHandler { 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[..]); From c5996d52ba571448edd3c9ddfbe775f1000ad066 Mon Sep 17 00:00:00 2001 From: Federico Franzoni <8609060+fed-franz@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:51:22 +0200 Subject: [PATCH 5/6] rusk: limit transaction number in new blocks --- rusk/src/lib/node/rusk.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rusk/src/lib/node/rusk.rs b/rusk/src/lib/node/rusk.rs index 39e3095c1b..f53c7657ce 100644 --- a/rusk/src/lib/node/rusk.rs +++ b/rusk/src/lib/node/rusk.rs @@ -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::{ @@ -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}"); From 693820233d0404ce25c591f7b6bea436c2448e0a Mon Sep 17 00:00:00 2001 From: Federico Franzoni <8609060+fed-franz@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:14:26 +0200 Subject: [PATCH 6/6] consensus: limit number of faults in new block --- consensus/src/proposal/block_generator.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/consensus/src/proposal/block_generator.rs b/consensus/src/proposal/block_generator.rs index e53a0585e4..d67348d6f9 100644 --- a/consensus/src/proposal/block_generator.rs +++ b/consensus/src/proposal/block_generator.rs @@ -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}; @@ -92,6 +92,13 @@ impl Generator { faults: &[Fault], voters: &[Voter], ) -> Result { + // 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)?;