Skip to content

Commit

Permalink
wip: revert faults_root removal
Browse files Browse the repository at this point in the history
  • Loading branch information
herr-seppia committed Jul 16, 2024
1 parent 75bbdd2 commit 81548c6
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 54 deletions.
16 changes: 16 additions & 0 deletions consensus/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use std::io;
use std::time::Duration;

use execution_core::StakePublicKey;
use node_data::ledger::Fault;
use node_data::ledger::InvalidFault;
use node_data::ledger::{Block, Header, Slash, SpentTransaction, Transaction};
use node_data::StepName;
use thiserror::Error;
Expand All @@ -29,6 +31,8 @@ pub enum Error {
MetricsUpdate(anyhow::Error),
#[error("Invalid Iteration Info {0}")]
InvalidIterationInfo(io::Error),
#[error("Invalid Faults {0}")]
InvalidFaults(InvalidFault),
}

impl From<io::Error> for Error {
Expand All @@ -37,6 +41,12 @@ impl From<io::Error> for Error {
}
}

impl From<InvalidFault> for Error {
fn from(value: InvalidFault) -> Self {
Self::InvalidFaults(value)
}
}

#[derive(Default, Clone, Debug)]
pub struct CallParams {
pub round: u64,
Expand Down Expand Up @@ -78,6 +88,12 @@ pub trait Operations: Send + Sync {
disable_winning_att_check: bool,
) -> Result<(u8, Vec<VoterWithCredits>, Vec<VoterWithCredits>), Error>;

async fn verify_faults(
&self,
block_height: u64,
faults: &[Fault],
) -> Result<(), Error>;

async fn verify_state_transition(
&self,
blk: &Block,
Expand Down
4 changes: 3 additions & 1 deletion consensus/src/proposal/block_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl<T: Operations> Generator<T> {
Seed::from(seed),
iteration,
failed_iterations,
&[],
ru.att_voters(),
)
.await?;
Expand Down Expand Up @@ -88,10 +89,11 @@ impl<T: Operations> Generator<T> {
seed: Seed,
iteration: u8,
failed_iterations: IterationsInfo,
faults: &[Fault],
voters: &[VoterWithCredits],
) -> Result<Block, crate::operations::Error> {
let to_slash =
Slash::from_iterations_and_faults(&failed_iterations, &faults)?;
Slash::from_iterations_and_faults(&failed_iterations, faults)?;

let call_params = CallParams {
round: ru.round,
Expand Down
31 changes: 15 additions & 16 deletions consensus/src/validation/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,40 +81,39 @@ impl<T: Operations + 'static> ValidationStep<T> {

// Verify candidate header (all fields except the winning attestation)
// NB: Winning attestation is produced only on reaching consensus
match executor.verify_block_header(header, true).await {
let vote = match executor.verify_block_header(header, true).await {
Ok((_, voters, _)) => {
// Call Verify State Transition to make sure transactions set is
// valid

// Voters here is the list of provisioners that validated the
// Tip of the current Block generator
let vote =
// TODO: Verify Faults
if let Err(err) = executor
.verify_faults(header.height, candidate.faults())
.await
{
error!(event = "invalid faults", ?err);
Vote::Invalid(header.hash)
} else {
match Self::call_vst(candidate, &voters, &executor).await {
Ok(_) => Vote::Valid(header.hash),
Err(err) => {
error!(event = "failed_vst_call", ?err);
Vote::Invalid(header.hash)
}
};

Self::cast_vote(vote, ru, iteration, outbound, inbound).await;
}
}
}
Err(err) => {
error!(event = "invalid_header", ?err, ?header);
// We should not vote Invalid if the candidate is not signed by
// the block producer.
// However, this is already verified in the Candidate message
// verification, so it's safe to vote invalid here
Self::cast_vote(
Vote::Invalid(header.hash),
ru,
iteration,
outbound,
inbound,
)
.await;
Vote::Invalid(header.hash)
}
}
};

Self::cast_vote(vote, ru, iteration, outbound, inbound).await;
}

async fn cast_vote(
Expand Down
4 changes: 2 additions & 2 deletions node-data/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod transaction;
pub use transaction::{SpentTransaction, Transaction};

mod faults;
pub use faults::Fault;
pub use faults::{Fault, Slash, SlashType, InvalidFault};

mod attestation;
pub use attestation::{
Expand All @@ -24,7 +24,7 @@ pub use attestation::{
use crate::bls::PublicKeyBytes;
use crate::Serializable;

use dusk_bytes::DeserializableSlice;
// use dusk_bytes::DeserializableSlice;
use rusk_abi::hash::Hasher;
use sha3::Digest;
use std::io::{self, Read, Write};
Expand Down
8 changes: 5 additions & 3 deletions node-data/src/ledger/faults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub enum InvalidFault {
RoundMismatch,
#[error("Invalid Signature {0}")]
InvalidSignature(BlsSigError),
#[error("Generic error {0}")]
Other(String),
}

impl From<BlsSigError> for InvalidFault {
Expand Down Expand Up @@ -328,10 +330,10 @@ impl Slash {
}))
}

pub fn from_header(header: &Header) -> Result<Vec<Slash>, io::Error> {
pub fn from_block(block: &Block) -> Result<Vec<Slash>, io::Error> {
Self::from_iterations_and_faults(
&header.failed_iterations,
&header.faults,
&block.header().failed_iterations,
block.faults(),
)
}

Expand Down
7 changes: 5 additions & 2 deletions node/src/chain/acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
let mut changed_provisioners = vec![reward, dusk_reward];

// Update provisioners if a slash has been applied
let slashed = Slash::from_header(blk.header())?
let slashed = Slash::from_block(blk)?
.into_iter()
.map(|f| ProvisionerChange::Slash(f.provisioner));
changed_provisioners.extend(slashed);
Expand Down Expand Up @@ -454,6 +454,9 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {

let vm = self.vm.write().await;
let (txs, rolling_result) = self.db.read().await.update(|db| {

// TODO: Verify Faults

let (txs, verification_output) =
vm.accept(blk, Some(&prev_block_voters[..]))?;

Expand All @@ -480,7 +483,7 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
header.height,
);

for slashed in Slash::from_header(blk.header())? {
for slashed in Slash::from_block(blk)? {
info!("Slashed {}", slashed.provisioner.to_base58());
slashed_count += 1;
}
Expand Down
15 changes: 14 additions & 1 deletion node/src/chain/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use dusk_consensus::operations::{
};
use dusk_consensus::queue::MsgRegistry;
use dusk_consensus::user::provisioners::ContextProvisioners;
use node_data::ledger::{Block, Header};
use node_data::ledger::{Block, Fault, Header};
use node_data::message::AsyncQueue;

use tokio::sync::{oneshot, Mutex, RwLock};
Expand Down Expand Up @@ -261,6 +261,19 @@ impl<DB: database::DB, VM: vm::VMExecution> Operations for Executor<DB, VM> {
.map_err(operations::Error::InvalidHeader)
}

async fn verify_faults(
&self,
block_height: u64,
faults: &[Fault],
) -> Result<(), Error> {
let validator = Validator::new(
self.db.clone(),
&self.tip_header,
&self.provisioners,
);
Ok(validator.verify_faults(block_height, faults).await?)
}

async fn verify_state_transition(
&self,
blk: &Block,
Expand Down
58 changes: 32 additions & 26 deletions node/src/chain/header_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use dusk_consensus::quorum::verifiers::QuorumResult;
use dusk_consensus::user::committee::{Committee, CommitteeSet};
use dusk_consensus::user::provisioners::{ContextProvisioners, Provisioners};
use execution_core::stake::EPOCH;
use node_data::ledger::Signature;
use node_data::ledger::{to_str, Header, Seed};
use node_data::ledger::{to_str, Fault, InvalidFault, Seed, Signature};
use node_data::message::payload::RatificationResult;
use node_data::message::ConsensusHeader;
use node_data::{ledger, StepName};
Expand Down Expand Up @@ -76,7 +75,7 @@ impl<'a, DB: database::DB> Validator<'a, DB> {
self.verify_success_att(candidate_block).await?;
}

self.verify_faults(candidate_block).await?;
// self.verify_faults(candidate_block).await?;

let pni = self.verify_failed_iterations(candidate_block).await?;
Ok((pni, prev_block_voters, candidate_block_voters))
Expand Down Expand Up @@ -283,36 +282,43 @@ impl<'a, DB: database::DB> Validator<'a, DB> {
/// Verify faults inside a block.
pub async fn verify_faults(
&self,
header: &ledger::Header,
) -> anyhow::Result<()> {
verify_faults(self.db.clone(), header).await
current_height: u64,
faults: &[Fault],
) -> Result<(), InvalidFault> {
verify_faults(self.db.clone(), current_height, faults).await
}
}

// TODO: verify faults
pub async fn verify_faults<DB: database::DB>(
db: Arc<RwLock<DB>>,
header: &Header,
) -> anyhow::Result<()> {
for f in &header.faults {
let fault_header = f.validate(header.height)?;
db.read().await.view(|db| {
let (prev_header, _) = db
.fetch_block_header(&fault_header.prev_block_hash)?
.ok_or(anyhow::anyhow!("Slashing a non accepted header"))?;
if prev_header.height != fault_header.round - 1 {
anyhow::bail!("Invalid height for fault");
}
current_height: u64,
faults: &[Fault],
) -> Result<(), InvalidFault> {
for f in faults {
let fault_header = f.validate(current_height)?;
db.read()
.await
.view(|db| {
let (prev_header, _) = db
.fetch_block_header(&fault_header.prev_block_hash)?
.ok_or(anyhow::anyhow!("Slashing a non accepted header"))?;
if prev_header.height != fault_header.round - 1 {
anyhow::bail!("Invalid height for fault");
}

// FIX_ME: Instead of fetching all store faults, check the fault id
// directly This needs the fault id to be changed into
// "HEIGHT|TYPE|PROV_KEY"
let stored_faults = db.fetch_faults(fault_header.round - EPOCH)?;
if stored_faults.iter().any(|other| f.same(other)) {
anyhow::bail!("Double fault detected");
}
// FIX_ME: Instead of fetching all store faults, check the fault
// id directly This needs the fault id to be
// changed into "HEIGHT|TYPE|PROV_KEY"
let stored_faults =
db.fetch_faults(fault_header.round - EPOCH)?;
if stored_faults.iter().any(|other| f.same(other)) {
anyhow::bail!("Double fault detected");
}

Ok(())
})?;
Ok(())
})
.map_err(|e| InvalidFault::Other(format!("{e:?}")))?;
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion rusk/benches/block_ingestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn accept_benchmark(c: &mut Criterion) {
generator,
txs,
None,
&[],
vec![],
None,
)
.expect("Accepting transactions should succeed");
Expand Down
4 changes: 2 additions & 2 deletions rusk/src/lib/chain/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl VMExecution for Rusk {
let generator = StakePublicKey::from_slice(&generator.0)
.map_err(|e| anyhow::anyhow!("Error in from_slice {e:?}"))?;

let slashing = Slash::from_header(blk.header())?;
let slashing = Slash::from_block(blk)?;

let (_, verification_output) = self
.verify_transactions(
Expand All @@ -76,7 +76,7 @@ impl VMExecution for Rusk {
let generator = StakePublicKey::from_slice(&generator.0)
.map_err(|e| anyhow::anyhow!("Error in from_slice {e:?}"))?;

let slashing = Slash::from_header(blk.header())?;
let slashing = Slash::from_block(blk)?;

let (txs, verification_output) = self
.accept_transactions(
Expand Down

0 comments on commit 81548c6

Please sign in to comment.