diff --git a/consensus/src/proposal/block_generator.rs b/consensus/src/proposal/block_generator.rs index b5d4e65ee7..20c4c081f4 100644 --- a/consensus/src/proposal/block_generator.rs +++ b/consensus/src/proposal/block_generator.rs @@ -115,9 +115,6 @@ impl Generator { let txs: Vec<_> = result.txs.into_iter().map(|t| t.inner).collect(); let txroot = merkle_root(&tx_hashes[..]); - let faults = Vec::::new(); - let faults_hashes: Vec<_> = faults.iter().map(|f| f.hash()).collect(); - let faultroot = merkle_root(&faults_hashes); let timestamp = max(ru.timestamp() + MINIMUM_BLOCK_TIME, get_current_timestamp()); @@ -136,11 +133,11 @@ impl Generator { att: Attestation::default(), prev_block_cert: *ru.att(), txroot, - faultroot, + faults, iteration, failed_iterations, }; - Ok(Block::new(blk_header, txs, faults).expect("block should be valid")) + Ok(Block::new(blk_header, txs).expect("block should be valid")) } } diff --git a/node-data/src/encoding.rs b/node-data/src/encoding.rs index c54f8c6a1f..3867a55d2f 100644 --- a/node-data/src/encoding.rs +++ b/node-data/src/encoding.rs @@ -10,7 +10,7 @@ use execution_core::transfer::Transaction as PhoenixTransaction; use crate::bls::PublicKeyBytes; use crate::ledger::{ - Attestation, Block, Fault, Header, IterationsInfo, Label, SpentTransaction, + Attestation, Block, Header, IterationsInfo, Label, SpentTransaction, StepVotes, Transaction, }; use crate::message::payload::{ @@ -30,12 +30,6 @@ impl Serializable for Block { t.write(w)?; } - let faults_len = self.faults().len() as u32; - w.write_all(&faults_len.to_le_bytes())?; - - for f in self.faults().iter() { - f.write(w)?; - } Ok(()) } @@ -52,14 +46,7 @@ impl Serializable for Block { .map(|_| Transaction::read(r)) .collect::, _>>()?; - // Read faults count - let faults_len = Self::read_u32_le(r)?; - - let faults = (0..faults_len) - .map(|_| Fault::read(r)) - .collect::, _>>()?; - - Block::new(header, txs, faults) + Block::new(header, txs) } } @@ -416,7 +403,10 @@ impl Serializable for QuorumType { #[cfg(test)] mod tests { - use crate::message::payload::{Candidate, Validation}; + use crate::{ + ledger::Fault, + message::payload::{Candidate, Validation}, + }; use super::*; use fake::{Dummy, Fake, Faker}; @@ -482,7 +472,7 @@ mod tests { } #[test] - fn test_encoding_faul() { + fn test_encoding_fault() { assert_serializable::(); } } diff --git a/node-data/src/ledger/block.rs b/node-data/src/ledger/block.rs index 56f49849aa..d90a9db0f9 100644 --- a/node-data/src/ledger/block.rs +++ b/node-data/src/ledger/block.rs @@ -12,7 +12,6 @@ pub type Hash = [u8; 32]; pub struct Block { header: Header, txs: Vec, - faults: Vec, } impl PartialEq for Block { @@ -25,16 +24,8 @@ impl Eq for Block {} impl Block { /// Creates a new block and calculates block hash, if missing. - pub fn new( - header: Header, - txs: Vec, - faults: Vec, - ) -> io::Result { - let mut b = Block { - header, - txs, - faults, - }; + pub fn new(header: Header, txs: Vec) -> io::Result { + let mut b = Block { header, txs }; b.calculate_hash()?; Ok(b) } @@ -58,13 +49,6 @@ impl Block { pub fn txs(&self) -> &Vec { &self.txs } - pub fn faults(&self) -> &Vec { - &self.faults - } - - pub fn into_faults(self) -> Vec { - self.faults - } pub fn set_attestation(&mut self, att: Attestation) { self.header.att = att; @@ -115,10 +99,10 @@ pub mod faker { gen_dummy_tx(rng.gen()), gen_dummy_tx(rng.gen()), ]; - let header: Header = Faker.fake(); - let faults = vec![Faker.fake(), Faker.fake(), Faker.fake()]; + let mut header: Header = Faker.fake(); + header.faults = vec![Faker.fake(), Faker.fake(), Faker.fake()]; - Block::new(header, txs, faults).expect("valid hash") + Block::new(header, txs).expect("valid hash") } } } diff --git a/node-data/src/ledger/faults.rs b/node-data/src/ledger/faults.rs index bffc214e66..8f30be2a88 100644 --- a/node-data/src/ledger/faults.rs +++ b/node-data/src/ledger/faults.rs @@ -303,10 +303,10 @@ impl Slash { })) } - pub fn from_block(blk: &Block) -> Result, io::Error> { + pub fn from_header(header: &Header) -> Result, io::Error> { Self::from_iterations_and_faults( - &blk.header().failed_iterations, - blk.faults(), + &header.failed_iterations, + &header.faults, ) } diff --git a/node-data/src/ledger/header.rs b/node-data/src/ledger/header.rs index 1566e45348..d53f0e230c 100644 --- a/node-data/src/ledger/header.rs +++ b/node-data/src/ledger/header.rs @@ -7,7 +7,7 @@ use super::*; pub type Seed = Signature; -#[derive(Default, Eq, PartialEq, Clone)] +#[derive(Default, Clone)] #[cfg_attr(any(feature = "faker", test), derive(Dummy))] pub struct Header { // Hashable fields @@ -20,11 +20,11 @@ pub struct Header { pub event_hash: Hash, pub generator_bls_pubkey: PublicKeyBytes, pub txroot: Hash, - pub faultroot: Hash, pub gas_limit: u64, pub iteration: u8, pub prev_block_cert: Attestation, pub failed_iterations: IterationsInfo, + pub faults: Vec, // Block hash pub hash: Hash, @@ -52,7 +52,7 @@ impl std::fmt::Debug for Header { .field("hash", &to_str(&self.hash)) .field("att", &self.att) .field("tx_root", &to_str(&self.txroot)) - .field("fault_root", &to_str(&self.faultroot)) + .field("fault_root", &self.faults) .finish() } } @@ -74,12 +74,18 @@ impl Header { w.write_all(&self.event_hash)?; w.write_all(self.generator_bls_pubkey.inner())?; w.write_all(&self.txroot)?; - w.write_all(&self.faultroot)?; w.write_all(&self.gas_limit.to_le_bytes())?; w.write_all(&self.iteration.to_le_bytes())?; self.prev_block_cert.write(w)?; self.failed_iterations.write(w)?; + let faults_len = self.faults.len() as u32; + w.write_all(&faults_len.to_le_bytes())?; + + for f in self.faults.iter() { + f.write(w)?; + } + Ok(()) } @@ -94,13 +100,19 @@ impl Header { let event_hash = Self::read_bytes(r)?; let generator_bls_pubkey = Self::read_bytes(r)?; let txroot = Self::read_bytes(r)?; - let faultroot = Self::read_bytes(r)?; let gas_limit = Self::read_u64_le(r)?; let iteration = Self::read_u8(r)?; let prev_block_cert = Attestation::read(r)?; let failed_iterations = IterationsInfo::read(r)?; + // Read faults count + let faults_len = Self::read_u32_le(r)?; + + let faults = (0..faults_len) + .map(|_| Fault::read(r)) + .collect::, _>>()?; + Ok(Header { version, height, @@ -113,7 +125,7 @@ impl Header { state_hash, event_hash, txroot, - faultroot, + faults, hash: [0; 32], att: Default::default(), prev_block_cert, diff --git a/node-data/src/message.rs b/node-data/src/message.rs index 48a0b6f644..f58d637c5d 100644 --- a/node-data/src/message.rs +++ b/node-data/src/message.rs @@ -1310,6 +1310,8 @@ impl std::fmt::Debug for SignInfo { #[cfg(test)] #[allow(unused)] mod tests { + use fake::Fake; + use self::payload::ValidationResult; use super::*; @@ -1338,7 +1340,7 @@ mod tests { event_hash: [5; 32], hash: [6; 32], txroot: [7; 32], - faultroot: [8; 32], + faults: vec![], att: Attestation { validation: ledger::StepVotes::new([6; 48], 22222222), ratification: ledger::StepVotes::new([7; 48], 3333333), @@ -1353,8 +1355,8 @@ mod tests { failed_iterations: Default::default(), }; - let sample_block = ledger::Block::new(header, vec![], vec![]) - .expect("should be valid block"); + let sample_block = + ledger::Block::new(header, vec![]).expect("should be valid block"); let sign_info = SignInfo { signer: bls::PublicKey::from_sk_seed_u64(3), diff --git a/node/src/chain.rs b/node/src/chain.rs index ad0f72a9bc..003a49be43 100644 --- a/node/src/chain.rs +++ b/node/src/chain.rs @@ -276,12 +276,7 @@ impl ChainSrv { let genesis_blk = genesis::generate_state(state); db.write().await.update(|t| { // Persist genesis block - t.store_block( - genesis_blk.header(), - &[], - &[], - Label::Final(0), - ) + t.store_block(genesis_blk.header(), &[], Label::Final(0)) })?; BlockWithLabel::new_with_label(genesis_blk, Label::Final(0)) diff --git a/node/src/chain/acceptor.rs b/node/src/chain/acceptor.rs index 09d190f582..eeeb8a8b3a 100644 --- a/node/src/chain/acceptor.rs +++ b/node/src/chain/acceptor.rs @@ -300,7 +300,7 @@ impl Acceptor { let mut changed_provisioners = vec![reward, dusk_reward]; // Update provisioners if a slash has been applied - let slashed = Slash::from_block(blk)? + let slashed = Slash::from_header(blk.header())? .into_iter() .map(|f| ProvisionerChange::Slash(f.provisioner)); changed_provisioners.extend(slashed); @@ -441,7 +441,8 @@ impl Acceptor { ) .await?; - header_validation::verify_faults(self.db.clone(), blk.faults()).await?; + header_validation::verify_faults(self.db.clone(), &blk.header().faults) + .await?; // Elapsed time header verification histogram!("dusk_block_header_elapsed") @@ -470,8 +471,7 @@ impl Acceptor { let label = rolling_results.0; // Store block with updated transactions with Error and GasSpent - block_size_on_disk = - db.store_block(header, &txs, blk.faults(), label)?; + block_size_on_disk = db.store_block(header, &txs, label)?; Ok((txs, rolling_results)) })?; @@ -483,7 +483,7 @@ impl Acceptor { header.height, ); - for slashed in Slash::from_block(blk)? { + for slashed in Slash::from_header(blk.header())? { info!("Slashed {}", slashed.provisioner.to_base58()); slashed_count += 1; } diff --git a/node/src/chain/genesis.rs b/node/src/chain/genesis.rs index d676bdd1cc..6d52cfb07c 100644 --- a/node/src/chain/genesis.rs +++ b/node/src/chain/genesis.rs @@ -16,7 +16,6 @@ pub(crate) fn generate_state(state_hash: [u8; 32]) -> Block { ..Default::default() }, vec![], - vec![], ) .expect("block should be valid") } diff --git a/node/src/database.rs b/node/src/database.rs index 5b7012ba5a..eeeee30693 100644 --- a/node/src/database.rs +++ b/node/src/database.rs @@ -52,7 +52,6 @@ pub trait Ledger { &self, header: &ledger::Header, txs: &[SpentTransaction], - faults: &[Fault], label: Label, ) -> Result; diff --git a/node/src/database/rocksdb.rs b/node/src/database/rocksdb.rs index 60043967e3..b958fed813 100644 --- a/node/src/database/rocksdb.rs +++ b/node/src/database/rocksdb.rs @@ -279,7 +279,6 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { &self, header: &ledger::Header, txs: &[SpentTransaction], - faults: &[Fault], label: Label, ) -> Result { // COLUMN FAMILY: CF_LEDGER_HEADER @@ -296,7 +295,11 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { .map(|t| t.inner.id()) .collect::>(), - faults_ids: faults.iter().map(|f| f.hash()).collect::>(), + faults_ids: header + .faults + .iter() + .map(|f| f.hash()) + .collect::>(), } .write(&mut buf)?; @@ -324,7 +327,7 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { let cf = self.ledger_faults_cf; // store all block faults - for f in faults { + for f in &header.faults { let mut d = vec![]; f.write(&mut d)?; self.put_cf(cf, f.hash(), d)?; @@ -351,7 +354,7 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { if block_height >= start_height { hash = block.header().prev_block_hash.to_vec(); - faults.extend(block.into_faults()); + faults.extend(block.header().faults.clone()); } else { break; } @@ -387,7 +390,7 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { for tx in b.txs() { self.inner.delete_cf(self.ledger_txs_cf, tx.id())?; } - for f in b.faults() { + for f in &b.header().faults { self.inner.delete_cf(self.ledger_faults_cf, f.hash())?; } @@ -438,7 +441,7 @@ impl<'db, DB: DBAccess> Ledger for DBTransaction<'db, DB> { } Ok(Some( - ledger::Block::new(record.header, txs, faults) + ledger::Block::new(record.header, txs) .expect("block should be valid"), )) } @@ -1005,7 +1008,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Final(3), )?; Ok(()) @@ -1028,10 +1030,10 @@ mod tests { // Assert all faults are fully fetched from ledger as // well. - for pos in 0..b.faults().len() { + for pos in 0..b.header().faults.len() { assert_eq!( - db_blk.faults()[pos].hash(), - b.faults()[pos].hash() + db_blk.header().faults[pos].hash(), + b.header().faults[pos].hash() ); } }); @@ -1062,7 +1064,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Final(3), ) .expect("block to be stored"); @@ -1092,7 +1093,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Final(3), ) .unwrap(); @@ -1246,7 +1246,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Final(3), )?; Ok(()) @@ -1281,7 +1280,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Attested(3), )?; Ok(()) @@ -1312,7 +1310,6 @@ mod tests { txn.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Attested(3), )?; Ok(()) @@ -1345,7 +1342,6 @@ mod tests { ut.store_block( b.header(), &to_spent_txs(b.txs()), - b.faults(), Label::Final(3), )?; Ok(()) diff --git a/rusk/src/lib/chain/vm.rs b/rusk/src/lib/chain/vm.rs index c0d699e4ee..6a5e363976 100644 --- a/rusk/src/lib/chain/vm.rs +++ b/rusk/src/lib/chain/vm.rs @@ -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_block(blk)?; + let slashing = Slash::from_header(blk.header())?; let (_, verification_output) = self .verify_transactions( @@ -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_block(blk)?; + let slashing = Slash::from_header(blk.header())?; let (txs, verification_output) = self .accept_transactions(