Skip to content

Commit a4af5d1

Browse files
committed
Adds child_blocks method and refactors invalidate_block in chain.rs. Refactors invalidate_block in NonFinalizedState.
1 parent 8cf06c6 commit a4af5d1

File tree

3 files changed

+38
-46
lines changed

3 files changed

+38
-46
lines changed

zebra-state/src/service/non_finalized_state.rs

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
constants::MAX_NON_FINALIZED_CHAIN_FORKS,
1919
request::{ContextuallyVerifiedBlock, FinalizableBlock},
2020
service::{check, finalized_state::ZebraDb},
21-
HashOrHeight, SemanticallyVerifiedBlock, ValidateContextError,
21+
SemanticallyVerifiedBlock, ValidateContextError,
2222
};
2323

2424
mod chain;
@@ -270,45 +270,33 @@ impl NonFinalizedState {
270270
Ok(())
271271
}
272272

273-
/// Invalidate block with has `block_hash` and all descendants from the non-finalized state. Insert
273+
/// Invalidate block with hash `block_hash` and all descendants from the non-finalized state. Insert
274274
/// the new chain into the chain_set and discard the previous.
275275
pub fn invalidate_block(&mut self, block_hash: Hash) {
276-
if !self.any_chain_contains(&block_hash) {
276+
let Some(chain) = self.find_chain(|chain| chain.contains_block_hash(block_hash)) else {
277277
return;
278-
}
279-
280-
let mut chain = self
281-
.find_chain(|chain| chain.contains_block_hash(block_hash))
282-
.expect("block hash exist in a chain");
278+
};
283279

284-
// If the non-finalized chain root has the intended hash drop the chain
285-
// and return early
286-
let root = chain
287-
.block(HashOrHeight::Height(chain.non_finalized_root_height()))
288-
.unwrap();
289-
if root.hash == block_hash {
280+
let invalidated_blocks = if chain.non_finalized_root_hash() == block_hash {
290281
self.chain_set.remove(&chain);
291-
self.update_metrics_for_chains();
292-
self.update_metrics_bars();
293-
return;
294-
}
282+
chain.blocks.values().cloned().collect()
283+
} else {
284+
let (new_chain, invalidated_blocks) = chain
285+
.invalidate_block(block_hash)
286+
.expect("already checked that chain contains hash");
287+
288+
// Add the new chain fork or updated chain to the set of recent chains, and
289+
// remove the chain containing the hash of the block from chain set
290+
self.insert_with(Arc::new(new_chain.clone()), |chain_set| {
291+
chain_set.retain(|c| !c.contains_block_hash(block_hash))
292+
});
295293

296-
let new_chain = Arc::make_mut(&mut chain);
297-
let block_height = new_chain.height_by_hash(block_hash).unwrap();
294+
invalidated_blocks
295+
};
298296

299-
let invalidated_descendants = new_chain.invalidate_block_and_descendants(&block_height);
300297
self.invalidated_blocks
301-
.insert(block_hash, Arc::new(invalidated_descendants));
298+
.insert(block_hash, Arc::new(invalidated_blocks));
302299

303-
// If the new chain still contains blocks:
304-
// - add the new chain fork or updated chain to the set of recent chains
305-
// - remove the chain containing the hash of the block from the chain set
306-
if !new_chain.is_empty() {
307-
self.insert_with(Arc::new(new_chain.clone()), |chain_set| {
308-
chain_set.retain(|c| !c.contains_block_hash(block_hash))
309-
});
310-
}
311-
312300
self.update_metrics_for_chains();
313301
self.update_metrics_bars();
314302
}

zebra-state/src/service/non_finalized_state/chain.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,24 @@ impl Chain {
343343
(block, treestate)
344344
}
345345

346-
pub fn invalidate_block_and_descendants(
347-
&mut self,
348-
height: &block::Height,
349-
) -> Vec<ContextuallyVerifiedBlock> {
350-
// Split the new chain at the the `block_hash` and invalidate the block with the
351-
// block_hash along with the block's descendants
352-
let invalidated_blocks = self.blocks.split_off(height);
353-
for (_, ctx_block) in invalidated_blocks.iter().rev() {
354-
self.revert_chain_with(ctx_block, RevertPosition::Tip);
355-
}
346+
// Returns the block at the provided height and all of its descendant blocks.
347+
pub fn child_blocks(&self, block_height: &block::Height) -> Vec<ContextuallyVerifiedBlock> {
348+
self.blocks
349+
.range(block_height..)
350+
.map(|(_h, b)| b.clone())
351+
.collect()
352+
}
356353

357-
invalidated_blocks.into_values().collect()
354+
// Returns a new chain without the invalidated block or its descendants.
355+
pub fn invalidate_block(
356+
&self,
357+
block_hash: block::Hash,
358+
) -> Option<(Self, Vec<ContextuallyVerifiedBlock>)> {
359+
let block_height = self.height_by_hash(block_hash)?;
360+
let mut new_chain = self.fork(block_hash)?;
361+
new_chain.pop_tip();
362+
new_chain.last_fork_height = None;
363+
Some((new_chain, self.child_blocks(&block_height)))
358364
}
359365

360366
/// Returns the height of the chain root.

zebra-state/src/service/non_finalized_state/tests/vectors.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,15 +279,13 @@ fn invalidate_block_removes_block_and_descendants_from_chain_for_network(
279279
Network::Mainnet => assert!(
280280
invalidated_blocks_state_descendants
281281
.iter()
282-
.find(|block| block.height == block::Height(653601))
283-
.is_some(),
282+
.any(|block| block.height == block::Height(653601)),
284283
"invalidated descendants vec should contain block3"
285284
),
286285
Network::Testnet(_parameters) => assert!(
287286
invalidated_blocks_state_descendants
288287
.iter()
289-
.find(|block| block.height == block::Height(584001))
290-
.is_some(),
288+
.any(|block| block.height == block::Height(584001)),
291289
"invalidated descendants vec should contain block3"
292290
),
293291
}

0 commit comments

Comments
 (0)