From 7ebb49ccb8dacd0492ce8faf053549fe1f581f34 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 30 Jun 2022 11:22:25 +0100 Subject: [PATCH 01/10] Limit number of elements loaded from the stagnant key This will likely be required if we enable stagnant prunning as currently database has way too many entries to be prunned in a single iteration --- node/core/chain-selection/src/backend.rs | 3 ++- .../core/chain-selection/src/db_backend/v1.rs | 22 +++++++++++++------ node/core/chain-selection/src/lib.rs | 8 ++++--- node/core/chain-selection/src/tests.rs | 5 ++++- node/core/chain-selection/src/tree.rs | 9 +++++++- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/node/core/chain-selection/src/backend.rs b/node/core/chain-selection/src/backend.rs index 71b6797d3526..6c5396a5c64d 100644 --- a/node/core/chain-selection/src/backend.rs +++ b/node/core/chain-selection/src/backend.rs @@ -46,10 +46,11 @@ pub(super) trait Backend { /// Load the stagnant list at the given timestamp. fn load_stagnant_at(&self, timestamp: Timestamp) -> Result, Error>; /// Load all stagnant lists up to and including the given Unix timestamp - /// in ascending order. + /// in ascending order. Stop fetching stagnant entries upon reaching `max_elements`. fn load_stagnant_at_up_to( &self, up_to: Timestamp, + max_elements: usize, ) -> Result)>, Error>; /// Load the earliest kept block number. fn load_first_block_number(&self) -> Result, Error>; diff --git a/node/core/chain-selection/src/db_backend/v1.rs b/node/core/chain-selection/src/db_backend/v1.rs index 8b4591f5c3a9..8037561afa07 100644 --- a/node/core/chain-selection/src/db_backend/v1.rs +++ b/node/core/chain-selection/src/db_backend/v1.rs @@ -229,6 +229,7 @@ impl Backend for DbBackend { fn load_stagnant_at_up_to( &self, up_to: crate::Timestamp, + max_elements: usize, ) -> Result)>, Error> { let stagnant_at_iter = self.inner.iter_with_prefix(self.config.col_data, &STAGNANT_AT_PREFIX[..]); @@ -240,7 +241,9 @@ impl Backend for DbBackend { _ => None, } }) - .take_while(|(at, _)| *at <= up_to.into()) + .enumerate() + .take_while(|(idx, (at, _))| *at <= up_to.into() && *idx < max_elements) + .map(|(_, v)| v) .collect::>(); Ok(val) @@ -528,7 +531,7 @@ mod tests { let mut backend = DbBackend::new(db, config); // Prove that it's cheap - assert!(backend.load_stagnant_at_up_to(Timestamp::max_value()).unwrap().is_empty()); + assert!(backend.load_stagnant_at_up_to(Timestamp::max_value(), usize::MAX).unwrap().is_empty()); backend .write(vec![ @@ -539,7 +542,7 @@ mod tests { .unwrap(); assert_eq!( - backend.load_stagnant_at_up_to(Timestamp::max_value()).unwrap(), + backend.load_stagnant_at_up_to(Timestamp::max_value(), usize::MAX).unwrap(), vec![ (2, vec![Hash::repeat_byte(1)]), (5, vec![Hash::repeat_byte(2)]), @@ -548,7 +551,7 @@ mod tests { ); assert_eq!( - backend.load_stagnant_at_up_to(10).unwrap(), + backend.load_stagnant_at_up_to(10, usize::MAX).unwrap(), vec![ (2, vec![Hash::repeat_byte(1)]), (5, vec![Hash::repeat_byte(2)]), @@ -557,21 +560,26 @@ mod tests { ); assert_eq!( - backend.load_stagnant_at_up_to(9).unwrap(), + backend.load_stagnant_at_up_to(9, usize::MAX).unwrap(), vec![(2, vec![Hash::repeat_byte(1)]), (5, vec![Hash::repeat_byte(2)]),] ); + assert_eq!( + backend.load_stagnant_at_up_to(9, 1).unwrap(), + vec![(2, vec![Hash::repeat_byte(1)]),] + ); + backend.write(vec![BackendWriteOp::DeleteStagnantAt(2)]).unwrap(); assert_eq!( - backend.load_stagnant_at_up_to(5).unwrap(), + backend.load_stagnant_at_up_to(5, usize::MAX).unwrap(), vec![(5, vec![Hash::repeat_byte(2)]),] ); backend.write(vec![BackendWriteOp::WriteStagnantAt(5, vec![])]).unwrap(); assert_eq!( - backend.load_stagnant_at_up_to(10).unwrap(), + backend.load_stagnant_at_up_to(10, usize::MAX).unwrap(), vec![(10, vec![Hash::repeat_byte(3)]),] ); } diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index a8646d874d8f..f9fe8188c8f4 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -50,6 +50,8 @@ type Timestamp = u64; // If a block isn't approved in 120 seconds, nodes will abandon it // and begin building on another chain. const STAGNANT_TIMEOUT: Timestamp = 120; +// Maximum number of stagnant entries cleaned during one `STAGNANT_TIMEOUT` iteration +const MAX_STAGNANT_ENTRIES: usize = 1000; #[derive(Debug, Clone)] enum Approval { @@ -435,7 +437,7 @@ where } } _ = stagnant_check_stream.next().fuse() => { - detect_stagnant(backend, clock.timestamp_now())?; + detect_stagnant(backend, clock.timestamp_now(), MAX_STAGNANT_ENTRIES)?; } } } @@ -637,9 +639,9 @@ fn handle_approved_block(backend: &mut impl Backend, approved_block: Hash) -> Re backend.write(ops) } -fn detect_stagnant(backend: &mut impl Backend, now: Timestamp) -> Result<(), Error> { +fn detect_stagnant(backend: &mut impl Backend, now: Timestamp, max_elements: usize) -> Result<(), Error> { let ops = { - let overlay = tree::detect_stagnant(&*backend, now)?; + let overlay = tree::detect_stagnant(&*backend, now, max_elements)?; overlay.into_write_ops() }; diff --git a/node/core/chain-selection/src/tests.rs b/node/core/chain-selection/src/tests.rs index 0b8947a200cf..20c4700dff57 100644 --- a/node/core/chain-selection/src/tests.rs +++ b/node/core/chain-selection/src/tests.rs @@ -139,13 +139,16 @@ impl Backend for TestBackend { fn load_stagnant_at_up_to( &self, up_to: Timestamp, + max_elements: usize, ) -> Result)>, Error> { Ok(self .inner .lock() .stagnant_at .range(..=up_to) - .map(|(t, v)| (*t, v.clone())) + .enumerate() + .take_while(|(idx, _)| *idx < max_elements) + .map(|(_, (t, v))| (*t, v.clone())) .collect()) } fn load_first_block_number(&self) -> Result, Error> { diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index d6f19b792a75..4a1384e513df 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -534,12 +534,15 @@ pub(super) fn approve_block( pub(super) fn detect_stagnant<'a, B: 'a + Backend>( backend: &'a B, up_to: Timestamp, + max_elements: usize, ) -> Result, Error> { - let stagnant_up_to = backend.load_stagnant_at_up_to(up_to)?; + let stagnant_up_to = backend.load_stagnant_at_up_to(up_to, max_elements)?; let mut backend = OverlayedBackend::new(backend); // As this is in ascending order, only the earliest stagnant // blocks will involve heavy viability propagations. + gum::debug!(target: LOG_TARGET, ?up_to, "Loaded {} stagnant entries", stagnant_up_to.len()); + for (timestamp, maybe_stagnant) in stagnant_up_to { backend.delete_stagnant_at(timestamp); @@ -550,6 +553,7 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( entry.viability.approval = Approval::Stagnant; } let is_viable = entry.viability.is_viable(); + gum::trace!(target: LOG_TARGET, ?block_hash, ?was_viable, is_viable, "Found existing stagnant entry"); if was_viable && !is_viable { propagate_viability_update(&mut backend, entry)?; @@ -557,6 +561,9 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( backend.write_block_entry(entry); } } + else { + gum::trace!(target: LOG_TARGET, ?block_hash, "Found non-existing stagnant entry"); + } } } From 2bb6f2619e83480810bf6d47ffd50ca39290979b Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 30 Jun 2022 11:24:28 +0100 Subject: [PATCH 02/10] Fmt run --- node/core/chain-selection/src/db_backend/v1.rs | 5 ++++- node/core/chain-selection/src/lib.rs | 6 +++++- node/core/chain-selection/src/tree.rs | 11 ++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/node/core/chain-selection/src/db_backend/v1.rs b/node/core/chain-selection/src/db_backend/v1.rs index 8037561afa07..db117ff945df 100644 --- a/node/core/chain-selection/src/db_backend/v1.rs +++ b/node/core/chain-selection/src/db_backend/v1.rs @@ -531,7 +531,10 @@ mod tests { let mut backend = DbBackend::new(db, config); // Prove that it's cheap - assert!(backend.load_stagnant_at_up_to(Timestamp::max_value(), usize::MAX).unwrap().is_empty()); + assert!(backend + .load_stagnant_at_up_to(Timestamp::max_value(), usize::MAX) + .unwrap() + .is_empty()); backend .write(vec![ diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index f9fe8188c8f4..be6509e54a29 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -639,7 +639,11 @@ fn handle_approved_block(backend: &mut impl Backend, approved_block: Hash) -> Re backend.write(ops) } -fn detect_stagnant(backend: &mut impl Backend, now: Timestamp, max_elements: usize) -> Result<(), Error> { +fn detect_stagnant( + backend: &mut impl Backend, + now: Timestamp, + max_elements: usize, +) -> Result<(), Error> { let ops = { let overlay = tree::detect_stagnant(&*backend, now, max_elements)?; diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index 4a1384e513df..1b09e650f212 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -553,15 +553,20 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( entry.viability.approval = Approval::Stagnant; } let is_viable = entry.viability.is_viable(); - gum::trace!(target: LOG_TARGET, ?block_hash, ?was_viable, is_viable, "Found existing stagnant entry"); + gum::trace!( + target: LOG_TARGET, + ?block_hash, + ?was_viable, + is_viable, + "Found existing stagnant entry" + ); if was_viable && !is_viable { propagate_viability_update(&mut backend, entry)?; } else { backend.write_block_entry(entry); } - } - else { + } else { gum::trace!(target: LOG_TARGET, ?block_hash, "Found non-existing stagnant entry"); } } From 5b388bce2dd9c8fcf4c6ec3a4e11bf5760a11738 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Jul 2022 09:33:45 +0100 Subject: [PATCH 03/10] Slightly improve logging --- node/core/chain-selection/src/tree.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index 1b09e650f212..e36526963a35 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -539,9 +539,22 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( let stagnant_up_to = backend.load_stagnant_at_up_to(up_to, max_elements)?; let mut backend = OverlayedBackend::new(backend); + let (min_ts, max_ts) = match stagnant_up_to.len() { + 0 => (0 as Timestamp, 0 as Timestamp), + 1 => (stagnant_up_to[0].0, stagnant_up_to[0].0), + n => (stagnant_up_to[0].0, stagnant_up_to[n - 1].0), + }; + // As this is in ascending order, only the earliest stagnant // blocks will involve heavy viability propagations. - gum::debug!(target: LOG_TARGET, ?up_to, "Loaded {} stagnant entries", stagnant_up_to.len()); + gum::debug!( + target: LOG_TARGET, + ?up_to, + ?min_ts, + ?max_ts, + "Prepared {} stagnant entries for pruning", + stagnant_up_to.len() + ); for (timestamp, maybe_stagnant) in stagnant_up_to { backend.delete_stagnant_at(timestamp); From a7427c3bb5c1c288797ad7054fab8e3f51cf2fa2 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Jul 2022 09:54:43 +0100 Subject: [PATCH 04/10] Some more debug nits --- node/core/chain-selection/src/tree.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index e36526963a35..6ea71bfeb8c5 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -569,8 +569,9 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( gum::trace!( target: LOG_TARGET, ?block_hash, + ?timestamp, ?was_viable, - is_viable, + ?is_viable, "Found existing stagnant entry" ); @@ -580,7 +581,7 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( backend.write_block_entry(entry); } } else { - gum::trace!(target: LOG_TARGET, ?block_hash, "Found non-existing stagnant entry"); + gum::trace!(target: LOG_TARGET, ?block_hash, ?timestamp, "Found non-existing stagnant entry"); } } } From 2461fcf901c2cc76d2f2fcb1c5ce4bc1b6259c85 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Jul 2022 09:56:51 +0100 Subject: [PATCH 05/10] Fmt pass --- node/core/chain-selection/src/tree.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index 6ea71bfeb8c5..5edb6748934d 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -581,7 +581,12 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( backend.write_block_entry(entry); } } else { - gum::trace!(target: LOG_TARGET, ?block_hash, ?timestamp, "Found non-existing stagnant entry"); + gum::trace!( + target: LOG_TARGET, + ?block_hash, + ?timestamp, + "Found non-existing stagnant entry" + ); } } } From 12e7ad8f4567ec81acd91064ee583f0a62e7d0e9 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Jul 2022 10:21:24 +0100 Subject: [PATCH 06/10] Add stagnant prunning delay --- node/core/chain-selection/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index be6509e54a29..bf3b18d8e4eb 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -50,6 +50,8 @@ type Timestamp = u64; // If a block isn't approved in 120 seconds, nodes will abandon it // and begin building on another chain. const STAGNANT_TIMEOUT: Timestamp = 120; +// Delay prunning of the stagnant keys by 25 hours to avoid interception with the finality +const STAGNANT_PRUNE_DELAY: Timestamp = 25 * 60 * 60; // Maximum number of stagnant entries cleaned during one `STAGNANT_TIMEOUT` iteration const MAX_STAGNANT_ENTRIES: usize = 1000; @@ -437,7 +439,10 @@ where } } _ = stagnant_check_stream.next().fuse() => { - detect_stagnant(backend, clock.timestamp_now(), MAX_STAGNANT_ENTRIES)?; + let now = clock.timestamp_now(); + if now > STAGNANT_PRUNE_DELAY { + detect_stagnant(backend, now - STAGNANT_PRUNE_DELAY, MAX_STAGNANT_ENTRIES)?; + } } } } From 5ae3fc65a4cc1ae7344bccd12b6414a40507ab51 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Jul 2022 10:21:49 +0100 Subject: [PATCH 07/10] Enable stagnant check worker --- node/service/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index 95b613d998f0..87cde77635be 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -930,7 +930,9 @@ where let chain_selection_config = ChainSelectionConfig { col_data: parachains_db::REAL_COLUMNS.col_chain_selection_data, - stagnant_check_interval: chain_selection_subsystem::StagnantCheckInterval::never(), + // Test enabling of the stagnant checks + //stagnant_check_interval: chain_selection_subsystem::StagnantCheckInterval::never(), + stagnant_check_interval: Default::default(), }; let dispute_coordinator_config = DisputeCoordinatorConfig { From 5e84d5e479f675789c67b6766b8664c9be7a3c4b Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 6 Jul 2022 16:43:20 +0100 Subject: [PATCH 08/10] Implement stagnant pruning without stagnant checks --- node/core/chain-selection/src/lib.rs | 62 +++++++++++++++++++++++--- node/core/chain-selection/src/tests.rs | 1 + node/core/chain-selection/src/tree.rs | 37 ++++++++++++++- node/service/src/lib.rs | 4 +- 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index 9dc8873c7130..77a1f0661255 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -50,7 +50,7 @@ type Timestamp = u64; // If a block isn't approved in 120 seconds, nodes will abandon it // and begin building on another chain. const STAGNANT_TIMEOUT: Timestamp = 120; -// Delay prunning of the stagnant keys by 25 hours to avoid interception with the finality +// Delay prunning of the stagnant keys in prune only mode by 25 hours to avoid interception with the finality const STAGNANT_PRUNE_DELAY: Timestamp = 25 * 60 * 60; // Maximum number of stagnant entries cleaned during one `STAGNANT_TIMEOUT` iteration const MAX_STAGNANT_ENTRIES: usize = 1000; @@ -299,6 +299,19 @@ impl StagnantCheckInterval { } } +/// Mode of the stagnant check operations: check and prune or prune only +#[derive(Debug, Clone)] +pub enum StagnantCheckMode { + CheckAndPrune, + PruneOnly, +} + +impl Default for StagnantCheckMode { + fn default() -> Self { + StagnantCheckMode::PruneOnly + } +} + /// Configuration for the chain selection subsystem. #[derive(Debug, Clone)] pub struct Config { @@ -306,6 +319,8 @@ pub struct Config { pub col_data: u32, /// How often to check for stagnant blocks. pub stagnant_check_interval: StagnantCheckInterval, + /// Mode of stagnant checks + pub stagnant_check_mode: StagnantCheckMode, } /// The chain selection subsystem. @@ -342,9 +357,15 @@ impl ChainSelectionSubsystem { ); SpawnedSubsystem { - future: run(ctx, backend, self.config.stagnant_check_interval, Box::new(SystemClock)) - .map(Ok) - .boxed(), + future: run( + ctx, + backend, + self.config.stagnant_check_interval, + self.config.stagnant_check_mode, + Box::new(SystemClock), + ) + .map(Ok) + .boxed(), name: "chain-selection-subsystem", } } @@ -355,12 +376,20 @@ async fn run( mut ctx: Context, mut backend: B, stagnant_check_interval: StagnantCheckInterval, + stagnant_check_mode: StagnantCheckMode, clock: Box, ) where B: Backend, { loop { - let res = run_until_error(&mut ctx, &mut backend, &stagnant_check_interval, &*clock).await; + let res = run_until_error( + &mut ctx, + &mut backend, + &stagnant_check_interval, + &stagnant_check_mode, + &*clock, + ) + .await; match res { Err(e) => { e.trace(); @@ -385,6 +414,7 @@ async fn run_until_error( ctx: &mut Context, backend: &mut B, stagnant_check_interval: &StagnantCheckInterval, + stagnant_check_mode: &StagnantCheckMode, clock: &(dyn Clock + Sync), ) -> Result<(), Error> where @@ -439,7 +469,13 @@ where } } _ = stagnant_check_stream.next().fuse() => { - detect_stagnant(backend, clock.timestamp_now(), MAX_STAGNANT_ENTRIES)?; + match stagnant_check_mode { + StagnantCheckMode::CheckAndPrune => detect_stagnant(backend, clock.timestamp_now(), MAX_STAGNANT_ENTRIES), + StagnantCheckMode::PruneOnly => { + let now_timestamp = clock.timestamp_now(); + prune_only_stagnant(backend, now_timestamp - STAGNANT_PRUNE_DELAY, MAX_STAGNANT_ENTRIES) + }, + }?; } } } @@ -655,6 +691,20 @@ fn detect_stagnant( backend.write(ops) } +fn prune_only_stagnant( + backend: &mut impl Backend, + now: Timestamp, + max_elements: usize, +) -> Result<(), Error> { + let ops = { + let overlay = tree::prune_only_stagnant(&*backend, now, max_elements)?; + + overlay.into_write_ops() + }; + + backend.write(ops) +} + // Load the leaves from the backend. If there are no leaves, then return // the finalized block. async fn load_leaves( diff --git a/node/core/chain-selection/src/tests.rs b/node/core/chain-selection/src/tests.rs index 20c4700dff57..404b854d894b 100644 --- a/node/core/chain-selection/src/tests.rs +++ b/node/core/chain-selection/src/tests.rs @@ -244,6 +244,7 @@ fn test_harness>( context, backend.clone(), StagnantCheckInterval::new(TEST_STAGNANT_INTERVAL), + StagnantCheckMode::CheckAndPrune, Box::new(clock.clone()), ); diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index 5edb6748934d..d011193711ea 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -552,7 +552,7 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( ?up_to, ?min_ts, ?max_ts, - "Prepared {} stagnant entries for pruning", + "Prepared {} stagnant entries for checking/pruning", stagnant_up_to.len() ); @@ -594,6 +594,41 @@ pub(super) fn detect_stagnant<'a, B: 'a + Backend>( Ok(backend) } +/// Prune stagnant entries at some timestamp without other checks +/// This function is intended just to clean leftover entries when the real +/// stagnant checks are disabled +pub(super) fn prune_only_stagnant<'a, B: 'a + Backend>( + backend: &'a B, + up_to: Timestamp, + max_elements: usize, +) -> Result, Error> { + let stagnant_up_to = backend.load_stagnant_at_up_to(up_to, max_elements)?; + let mut backend = OverlayedBackend::new(backend); + + let (min_ts, max_ts) = match stagnant_up_to.len() { + 0 => (0 as Timestamp, 0 as Timestamp), + 1 => (stagnant_up_to[0].0, stagnant_up_to[0].0), + n => (stagnant_up_to[0].0, stagnant_up_to[n - 1].0), + }; + + // As this is in ascending order, only the earliest stagnant + // blocks will involve heavy viability propagations. + gum::debug!( + target: LOG_TARGET, + ?up_to, + ?min_ts, + ?max_ts, + "Prepared {} stagnant entries for pruning", + stagnant_up_to.len() + ); + + for (timestamp, _) in stagnant_up_to { + backend.delete_stagnant_at(timestamp); + } + + Ok(backend) +} + /// Revert the tree to the block relative to `hash`. /// /// This accepts a fresh backend and returns an overlay on top of it representing diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index 87cde77635be..0f131280b51d 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -930,9 +930,8 @@ where let chain_selection_config = ChainSelectionConfig { col_data: parachains_db::REAL_COLUMNS.col_chain_selection_data, - // Test enabling of the stagnant checks - //stagnant_check_interval: chain_selection_subsystem::StagnantCheckInterval::never(), stagnant_check_interval: Default::default(), + stagnant_check_mode: chain_selection_subsystem::StagnantCheckMode::PruneOnly, }; let dispute_coordinator_config = DisputeCoordinatorConfig { @@ -1479,6 +1478,7 @@ fn revert_chain_selection(db: Arc, hash: Hash) -> sp_blockchain::R let config = chain_selection_subsystem::Config { col_data: parachains_db::REAL_COLUMNS.col_chain_selection_data, stagnant_check_interval: chain_selection_subsystem::StagnantCheckInterval::never(), + stagnant_check_mode: chain_selection_subsystem::StagnantCheckMode::PruneOnly, }; let chain_selection = chain_selection_subsystem::ChainSelectionSubsystem::new(config, db); From ff499e57723e047c89ca89d24b5025f52c59346c Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 7 Jul 2022 13:28:30 +0100 Subject: [PATCH 09/10] Update node/core/chain-selection/src/tree.rs Co-authored-by: Andronik --- node/core/chain-selection/src/tree.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/node/core/chain-selection/src/tree.rs b/node/core/chain-selection/src/tree.rs index d011193711ea..aafd75de5f97 100644 --- a/node/core/chain-selection/src/tree.rs +++ b/node/core/chain-selection/src/tree.rs @@ -611,8 +611,6 @@ pub(super) fn prune_only_stagnant<'a, B: 'a + Backend>( n => (stagnant_up_to[0].0, stagnant_up_to[n - 1].0), }; - // As this is in ascending order, only the earliest stagnant - // blocks will involve heavy viability propagations. gum::debug!( target: LOG_TARGET, ?up_to, From 4f460b84c40a960d4b1f6dff41dbdb0535ec6815 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 7 Jul 2022 15:10:06 +0100 Subject: [PATCH 10/10] Apply suggestions from code review Co-authored-by: Andronik --- node/core/chain-selection/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index 77a1f0661255..eb5ceac9b768 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -693,11 +693,11 @@ fn detect_stagnant( fn prune_only_stagnant( backend: &mut impl Backend, - now: Timestamp, + up_to: Timestamp, max_elements: usize, ) -> Result<(), Error> { let ops = { - let overlay = tree::prune_only_stagnant(&*backend, now, max_elements)?; + let overlay = tree::prune_only_stagnant(&*backend, up_to, max_elements)?; overlay.into_write_ops() };