From 945d3503d6263a416449092766fd6f8c40a719c4 Mon Sep 17 00:00:00 2001 From: Sydhds Date: Wed, 26 Apr 2023 18:37:25 +0200 Subject: [PATCH] Check draws before executing a denunciation (#3872) * Check draws before executing a denunciation * Fix pos check order * Simplify pos draws check --------- Co-authored-by: sydhds --- massa-execution-worker/src/context.rs | 4 +- massa-execution-worker/src/execution.rs | 50 +++++++++++++++++-- .../src/tests/scenarios_mandatories.rs | 6 +-- massa-execution-worker/src/worker.rs | 1 + massa-models/src/denunciation.rs | 8 +++ massa-pool-worker/src/denunciation_pool.rs | 6 +-- 6 files changed, 63 insertions(+), 12 deletions(-) diff --git a/massa-execution-worker/src/context.rs b/massa-execution-worker/src/context.rs index 4a22696a127..d415a85228e 100644 --- a/massa-execution-worker/src/context.rs +++ b/massa-execution-worker/src/context.rs @@ -962,8 +962,8 @@ impl ExecutionContext { self.speculative_executed_ops.is_op_executed(op_id) } - /// Check if a denunciation was previously processed (to prevent reuse) - pub fn is_denunciation_processed(&self, de_idx: &DenunciationIndex) -> bool { + /// Check if a denunciation was previously executed (to prevent reuse) + pub fn is_denunciation_executed(&self, de_idx: &DenunciationIndex) -> bool { self.speculative_processed_denunciations .is_denunciation_executed(de_idx) } diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index a20fe57bbf3..cf3ed391e74 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -83,6 +83,8 @@ pub(crate) struct ExecutionState { vesting_manager: Arc, // MipStore (Versioning) mip_store: MipStore, + // selector controller to get draws + selector: Box, } impl ExecutionState { @@ -98,6 +100,7 @@ impl ExecutionState { config: ExecutionConfig, final_state: Arc>, mip_store: MipStore, + selector: Box, ) -> ExecutionState { // Get the slot at the output of which the final state is attached. // This should be among the latest final slots. @@ -162,6 +165,7 @@ impl ExecutionState { config, vesting_manager, mip_store, + selector, } } @@ -450,19 +454,59 @@ impl ExecutionState { // ignore the denunciation if it was already executed let de_idx = DenunciationIndex::from(denunciation); - if context.is_denunciation_processed(&de_idx) { + if context.is_denunciation_executed(&de_idx) { return Err(ExecutionError::IncludeDenunciationError( "Denunciation was already executed".to_string(), )); } + // Check selector + // Note 1: Has to be done after slot limit and executed check + // Note 2: that this is done for a node to create a Block with 'fake' denunciation thus + // include them in executed denunciation and prevent (by occupying the corresponding entry) + // any further 'real' denunciation. + + match &denunciation { + Denunciation::Endorsement(_de) => { + // Get selected address from selector and check + let selection = self + .selector + .get_selection(*de_slot) + .expect("Could not get producer from selector"); + let selected_addr = selection + .endorsements + .get(*denunciation.get_index().unwrap_or(&0) as usize) + .expect("could not get selection for endorsement at index"); + + if *selected_addr != addr_denounced { + return Err(ExecutionError::IncludeDenunciationError( + "Attempt to execute a denunciation but address was not selected" + .to_string(), + )); + } + } + Denunciation::BlockHeader(_de) => { + let selected_addr = self + .selector + .get_producer(*de_slot) + .expect("Cannot get producer from selector"); + + if selected_addr != addr_denounced { + return Err(ExecutionError::IncludeDenunciationError( + "Attempt to execute a denunciation but address was not selected" + .to_string(), + )); + } + } + } + + context.insert_executed_denunciation(&de_idx); + let slashed = context.try_slash_rolls( &addr_denounced, self.config.roll_count_to_slash_on_denunciation, ); - context.insert_executed_denunciation(&de_idx); - match slashed { Ok(slashed_amount) => { // Add slashed amount / 2 to block reward diff --git a/massa-execution-worker/src/tests/scenarios_mandatories.rs b/massa-execution-worker/src/tests/scenarios_mandatories.rs index 87d6acdac6a..4867aad21a2 100644 --- a/massa-execution-worker/src/tests/scenarios_mandatories.rs +++ b/massa-execution-worker/src/tests/scenarios_mandatories.rs @@ -14,9 +14,7 @@ mod tests { MIP_STORE_STATS_COUNTERS_MAX, }; use massa_models::prehash::PreHashMap; - use massa_models::test_exports::{ - gen_block_headers_for_denunciation, gen_endorsements_for_denunciation, - }; + use massa_models::test_exports::gen_endorsements_for_denunciation; use massa_models::{address::Address, amount::Amount, slot::Slot}; use massa_models::{ block_id::BlockId, @@ -1846,7 +1844,7 @@ mod tests { // create a denunciation let (_slot, _keypair, s_endorsement_1, s_endorsement_2, _) = - gen_block_headers_for_denunciation(Some(Slot::new(2, 4)), Some(keypair)); + gen_endorsements_for_denunciation(Some(Slot::new(2, 4)), Some(keypair)); let denunciation = Denunciation::try_from((&s_endorsement_1, &s_endorsement_2)).unwrap(); // create the block containing the roll buy operation diff --git a/massa-execution-worker/src/worker.rs b/massa-execution-worker/src/worker.rs index 735eb0aba6e..db06178cdfc 100644 --- a/massa-execution-worker/src/worker.rs +++ b/massa-execution-worker/src/worker.rs @@ -253,6 +253,7 @@ pub fn start_execution_worker( config.clone(), final_state, mip_store, + selector.clone(), ))); // define the input data interface diff --git a/massa-models/src/denunciation.rs b/massa-models/src/denunciation.rs index b3c92fd22ea..ee7f26c0659 100644 --- a/massa-models/src/denunciation.rs +++ b/massa-models/src/denunciation.rs @@ -250,6 +250,14 @@ impl Denunciation { } } + /// Get field: index (return None for a block header denunciation) + pub fn get_index(&self) -> Option<&u32> { + match self { + Denunciation::BlockHeader(_) => None, + Denunciation::Endorsement(de) => Some(&de.index), + } + } + /// Get Denunciation public key ref pub fn get_public_key(&self) -> &PublicKey { match self { diff --git a/massa-pool-worker/src/denunciation_pool.rs b/massa-pool-worker/src/denunciation_pool.rs index 52c2b8fa2fa..3b5bdac5dc1 100644 --- a/massa-pool-worker/src/denunciation_pool.rs +++ b/massa-pool-worker/src/denunciation_pool.rs @@ -110,11 +110,11 @@ impl DenunciationPool { Ok(selection) => { if let Some(address) = selection.endorsements.get(de_p.index as usize) { if *address != Address::from_public_key(&de_p.public_key) { - warn!("Denunciation factory received a secure share endorsement but address was not selected"); + warn!("Denunciation pool received a secure share endorsement but address was not selected"); return; } } else { - warn!("Denunciation factory could not get selected address for endorsements at index"); + warn!("Denunciation pool could not get selected address for endorsements at index"); return; } } @@ -131,7 +131,7 @@ impl DenunciationPool { if address != Address::from_public_key(denunciation_precursor.get_public_key()) { - warn!("Denunciation factory received a secured header but address was not selected"); + warn!("Denunciation pool received a secured header but address was not selected"); return; } }