Turn the relevant chain into a Vec before using it
Some checks use the same blocks, so we take a copy of the block borrows
before using them. That way, we don't have to manage the position of the
iterator between checks.
@@ -47,10 +47,15 @@ where
.expect("finalized state must contain at least one block to do contextual validation");
check::block_is_not_orphaned(finalized_tip_height, prepared.height)?;
- // Peek at the first block
- let mut relevant_chain = relevant_chain.into_iter().peekable();
+ // The maximum number of blocks used by contextual checks
+ const MAX_CONTEXT_BLOCKS: usize = POW_AVERAGING_WINDOW + POW_MEDIAN_BLOCK_SPAN;
+ let relevant_chain: Vec<_> = relevant_chain
+ .into_iter()
+ .take(MAX_CONTEXT_BLOCKS)
+ .collect();
+
let parent_block = relevant_chain
- .peek()
+ .get(0)
.expect("state must contain parent block to do contextual validation");
let parent_block = parent_block.borrow();
let parent_height = parent_block
@@ -58,18 +63,13 @@ where
.expect("valid blocks have a coinbase height");
check::height_one_more_than_parent_height(parent_height, prepared.height)?;
- // Note: the difficulty check reads the first 28 blocks from the relevant
- // chain iterator. If you want to use those blocks in other checks, you'll
- // need to clone them here.
-
if relevant_chain.len() >= POW_AVERAGING_WINDOW + POW_MEDIAN_BLOCK_SPAN {
- let relevant_data = relevant_chain.map(|block| {
+ let relevant_data = relevant_chain.iter().map(|block| {
(
block.borrow().header.difficulty_threshold,
block.borrow().header.time,
)
});
- // Reads the first 28 blocks from the iterator
let expected_difficulty =
AdjustedDifficulty::new_from_block(&prepared.block, network, relevant_data);
check::difficulty_threshold_is_valid(
