fn validate_blocks(&self, pool_reader: &PoolReader<'_>) -> ChangeSet {
        let mut change_set = Vec::new();

        let notarization_height = pool_reader.get_notarized_height();
        let finalized_height = pool_reader.get_finalized_height();
        let max_height = notarization_height.increment();
        let range = HeightRange::new(finalized_height.increment(), max_height);
        // Collect the min of validated block proposal ranks in the range.
        let mut known_ranks: BTreeMap<Height, Option<Rank>> =
            get_min_validated_ranks(pool_reader, &range);
        let dkg_pool = &*self.dkg_pool.read().unwrap();

        // It is necessary to traverse all the proposals and not only the ones with min
        // rank per height; because proposals for which there is an unvalidated
        // notarization are considered even if there is a lower rank proposal.
        for proposal in pool_reader
            .pool()
            .unvalidated()
            .block_proposal()
            .get_by_height_range(range)
        {
            if proposal.check_integrity() {
                // Attempt to validate the proposal through a notarization
                if let Some(notarization) = pool_reader
                    .pool()
                    .unvalidated()
                    .notarization()
                    .get_by_height(proposal.height())
                    .find(|notarization| &notarization.content.block == proposal.content.get_hash())
                {
                    // Verify notarization signature before checking block validity.
                    let verification = self.verify_signature(pool_reader, &notarization);
                    if let Err(ValidationError::Permanent(e)) = verification {
                        change_set.push(ChangeAction::HandleInvalid(
                            notarization.into_message(),
                            format!("{:?}", e),
                        ));
                        continue;
                    } else if verification.is_ok() {
                        if get_notarized_parent(pool_reader, &proposal).is_ok() {
                            self.metrics.observe_block(pool_reader, &proposal);
                            known_ranks.insert(proposal.height(), Some(proposal.rank()));
                            change_set.push(ChangeAction::MoveToValidated(proposal.into_message()));
                            change_set
                                .push(ChangeAction::MoveToValidated(notarization.into_message()));
                        }
                        // If the parent is notarized, this block and its notarization are
                        // validated. If not, this block currently cannot be
                        // validated through parent either.
                        continue;
                    }
                    // Note that transient errors on notarization signature
                    // verification should cause fall through, and the block
                    // proposals proceed to be checked normally.
                }

                // Skip validation and drop the block if it has a higher rank than a known valid
                // block. Note that this must happen after we first allow "block with
                // notarization" validation (see above). Otherwise we may get stuck when a block
                // maker equivocates.
                if let Some(Some(min_rank)) = known_ranks.get(&proposal.height()) {
                    if proposal.rank() > *min_rank {
                        // Skip them instead of removal because we don't want to end up
                        // requesting these artifacts again.
                        let id = proposal.get_id();
                        if self.unvalidated_for_too_long(pool_reader, &id) {
                            warn!(every_n_seconds => LOG_EVERY_N_SECONDS,
                                  self.log,
                                  "Due a valid proposal with a lower rank {}, /
                                  skipping validating the proposal: {:?} with rank {}",
                                  min_rank.0, id, proposal.rank().0
                            );
                        }
                        continue;
                    }
                }

                // We only validate blocks from a block maker of a certain rank after a
                // rank-based delay. If this time has not elapsed yet, we ignore the block for
                // now.
                if !is_time_to_make_block(
                    &self.log,
                    self.registry_client.as_ref(),
                    self.replica_config.subnet_id,
                    pool_reader,
                    proposal.height(),
                    proposal.rank(),
                    self.time_source.as_ref(),
                ) {
                    continue;
                }

                match self.check_block_validity(pool_reader, &proposal, dkg_pool) {
                    Ok(()) => {
                        self.metrics.observe_block(pool_reader, &proposal);
                        known_ranks.insert(proposal.height(), Some(proposal.rank()));
                        change_set.push(ChangeAction::MoveToValidated(proposal.into_message()))
                    }
                    Err(ValidationError::Permanent(err)) => change_set.push(
                        ChangeAction::HandleInvalid(proposal.into_message(), format!("{:?}", err)),
                    ),
                    Err(ValidationError::Transient(err)) => {
                        if self.unvalidated_for_too_long(pool_reader, &proposal.get_id()) {
                            warn!(every_n_seconds => LOG_EVERY_N_SECONDS,
                                  self.log,
                                  "Couldn't check the block validity: {:?}", err
                            );
                        }
                    }
                }
            } else {
                warn!(
                    self.log,
                    "Invalid block (compromised payload integrity): {:?}", proposal
                );
                change_set.push(ChangeAction::HandleInvalid(
                    proposal.clone().into_message(),
                    format!(
                        "Proposal integrity check failed: {:?} {:?} {:?}",
                        proposal.content.get_hash(),
                        proposal.as_ref().payload.get_hash(),
                        proposal.as_ref().payload.as_ref()
                    ),
                ))
            }
        }
        self.metrics.observe_and_reset_dkg_time_per_validator_run();
        change_set
    }
/// Return a `ChangeSet` containing status updates concerning any currently
/// unvalidated blocks that can now be marked valid or invalid. See
/// `check_block_validity`.
Return a `ChangeSet` containing status updates concerning any currently
unvalidated blocks that can now be marked valid or invalid.
Return a ` ChangeSet ` containing status updates concerning any currently unvalidated blocks that can now be marked valid or invalid .
fn validate_blocks(&self, pool_reader: &PoolReader<'_>) -> ChangeSet {
        let mut change_set = Vec::new();
        let notarization_height = pool_reader.get_notarized_height();
        let finalized_height = pool_reader.get_finalized_height();
        let max_height = notarization_height.increment();
        let range = HeightRange::new(finalized_height.increment(), max_height);
        // Collect the min of validated block proposal ranks in the range.
        let mut known_ranks: BTreeMap<Height, Option<Rank>> =
            get_min_validated_ranks(pool_reader, &range);
        let dkg_pool = &*self.dkg_pool.read().unwrap();
        // It is necessary to traverse all the proposals and not only the ones with min
        // rank per height; because proposals for which there is an unvalidated
        // notarization are considered even if there is a lower rank proposal.
        for proposal in pool_reader
            .pool()
            .unvalidated()
            .block_proposal()
            .get_by_height_range(range)
        {
            if proposal.check_integrity() {
                // Attempt to validate the proposal through a notarization
                if let Some(notarization) = pool_reader
                    .pool()
                    .unvalidated()
                    .notarization()
                    .get_by_height(proposal.height())
                    .find(|notarization| &notarization.content.block == proposal.content.get_hash())
                {
                    // Verify notarization signature before checking block validity.
                    let verification = self.verify_signature(pool_reader, &notarization);
                    if let Err(ValidationError::Permanent(e)) = verification {
                        change_set.push(ChangeAction::HandleInvalid(
                            notarization.into_message(),
                            format!("{:?}", e),
                        ));
                        continue;
                    } else if verification.is_ok() {
                        if get_notarized_parent(pool_reader, &proposal).is_ok() {
                            self.metrics.observe_block(pool_reader, &proposal);
                            known_ranks.insert(proposal.height(), Some(proposal.rank()));
                            change_set.push(ChangeAction::MoveToValidated(proposal.into_message()));
                            change_set
                                .push(ChangeAction::MoveToValidated(notarization.into_message()));
                        }
                        // If the parent is notarized, this block and its notarization are
                        // validated. If not, this block currently cannot be
                        // validated through parent either.
                        continue;
                    }
                    // Note that transient errors on notarization signature
                    // verification should cause fall through, and the block
                    // proposals proceed to be checked normally.
                }
                // Skip validation and drop the block if it has a higher rank than a known valid
                // block. Note that this must happen after we first allow "block with
                // notarization" validation (see above). Otherwise we may get stuck when a block
                // maker equivocates.
                if let Some(Some(min_rank)) = known_ranks.get(&proposal.height()) {
                    if proposal.rank() > *min_rank {
                        // Skip them instead of removal because we don't want to end up
                        // requesting these artifacts again.
                        let id = proposal.get_id();
                        if self.unvalidated_for_too_long(pool_reader, &id) {
                            warn!(every_n_seconds => LOG_EVERY_N_SECONDS,
                                  self.log,
                                  "Due a valid proposal with a lower rank {}, /
                                  skipping validating the proposal: {:?} with rank {}",
                                  min_rank.0, id, proposal.rank().0
                            );
                        }
                        continue;
                    }
                }
                // We only validate blocks from a block maker of a certain rank after a
                // rank-based delay. If this time has not elapsed yet, we ignore the block for
                // now.
                if !is_time_to_make_block(
                    &self.log,
                    self.registry_client.as_ref(),
                    self.replica_config.subnet_id,
                    pool_reader,
                    proposal.height(),
                    proposal.rank(),
                    self.time_source.as_ref(),
                ) {
                    continue;
                }
                match self.check_block_validity(pool_reader, &proposal, dkg_pool) {
                    Ok(()) => {
                        self.metrics.observe_block(pool_reader, &proposal);
                        known_ranks.insert(proposal.height(), Some(proposal.rank()));
                        change_set.push(ChangeAction::MoveToValidated(proposal.into_message()))
                    }
                    Err(ValidationError::Permanent(err)) => change_set.push(
                        ChangeAction::HandleInvalid(proposal.into_message(), format!("{:?}", err)),
                    ),
                    Err(ValidationError::Transient(err)) => {
                        if self.unvalidated_for_too_long(pool_reader, &proposal.get_id()) {
                            warn!(every_n_seconds => LOG_EVERY_N_SECONDS,
                                  self.log,
                                  "Couldn't check the block validity: {:?}", err
                            );
                        }
                    }
                }
            } else {
                warn!(
                    self.log,
                    "Invalid block (compromised payload integrity): {:?}", proposal
                );
                change_set.push(ChangeAction::HandleInvalid(
                    proposal.clone().into_message(),
                    format!(
                        "Proposal integrity check failed: {:?} {:?} {:?}",
                        proposal.content.get_hash(),
                        proposal.as_ref().payload.get_hash(),
                        proposal.as_ref().payload.as_ref()
                    ),
                ))
            }
        }
        self.metrics.observe_and_reset_dkg_time_per_validator_run();
        change_set
    }
fn validate_blocks ( & self , pool_reader : & PoolReader < ' _ > ) -> ChangeSet { let mut change_set = Vec :: new ( ) ; let notarization_height = pool_reader . get_notarized_height ( ) ; let finalized_height = pool_reader . get_finalized_height ( ) ; let max_height = notarization_height . increment ( ) ; let range = HeightRange :: new ( finalized_height . increment ( ) , max_height ) ; // Collect the min of validated block proposal ranks in the range. let mut known_ranks : BTreeMap < Height , Option < Rank > > = get_min_validated_ranks ( pool_reader , & range ) ; let dkg_pool = & * self . dkg_pool . read ( ) . unwrap ( ) ; // It is necessary to traverse all the proposals and not only the ones with min // rank per height; because proposals for which there is an unvalidated // notarization are considered even if there is a lower rank proposal. for proposal in pool_reader . pool ( ) . unvalidated ( ) . block_proposal ( ) . get_by_height_range ( range ) { if proposal . check_integrity ( ) { // Attempt to validate the proposal through a notarization if let Some ( notarization ) = pool_reader . pool ( ) . unvalidated ( ) . notarization ( ) . get_by_height ( proposal . height ( ) ) . find ( | notarization | & notarization . content . block == proposal . content . get_hash ( ) ) { // Verify notarization signature before checking block validity. let verification = self . verify_signature ( pool_reader , & notarization ) ; if let Err ( ValidationError :: Permanent ( e ) ) = verification { change_set . push ( ChangeAction :: HandleInvalid ( notarization . into_message ( ) , format ! ( " " e ) , ) ) ; continue ; } else if verification . is_ok ( ) { if get_notarized_parent ( pool_reader , & proposal ) . is_ok ( ) { self . metrics . observe_block ( pool_reader , & proposal ) ; known_ranks . insert ( proposal . height ( ) , Some ( proposal . rank ( ) ) ) ; change_set . push ( ChangeAction :: MoveToValidated ( proposal . into_message ( ) ) ) ; change_set . push ( ChangeAction :: MoveToValidated ( notarization . into_message ( ) ) ) ; } // If the parent is notarized, this block and its notarization are // validated. If not, this block currently cannot be // validated through parent either. continue ; } // Note that transient errors on notarization signature // verification should cause fall through, and the block // proposals proceed to be checked normally. } // Skip validation and drop the block if it has a higher rank than a known valid // block. Note that this must happen after we first allow "block with // notarization" validation (see above). Otherwise we may get stuck when a block // maker equivocates. if let Some ( Some ( min_rank ) ) = known_ranks . get ( & proposal . height ( ) ) { if proposal . rank ( ) > * min_rank { // Skip them instead of removal because we don't want to end up // requesting these artifacts again. let id = proposal . get_id ( ) ; if self . unvalidated_for_too_long ( pool_reader , & id ) { warn ! ( every_n_seconds LOG_EVERY_N_SECONDS self log " " min_rank 0 id proposal rank ( ) 0 ) ; } continue ; } } // We only validate blocks from a block maker of a certain rank after a // rank-based delay. If this time has not elapsed yet, we ignore the block for // now. if ! is_time_to_make_block ( & self . log , self . registry_client . as_ref ( ) , self . replica_config . subnet_id , pool_reader , proposal . height ( ) , proposal . rank ( ) , self . time_source . as_ref ( ) , ) { continue ; } match self . check_block_validity ( pool_reader , & proposal , dkg_pool ) { Ok ( ( ) ) => { self . metrics . observe_block ( pool_reader , & proposal ) ; known_ranks . insert ( proposal . height ( ) , Some ( proposal . rank ( ) ) ) ; change_set . push ( ChangeAction :: MoveToValidated ( proposal . into_message ( ) ) ) } Err ( ValidationError :: Permanent ( err ) ) => change_set . push ( ChangeAction :: HandleInvalid ( proposal . into_message ( ) , format ! ( " " err ) ) , ) , Err ( ValidationError :: Transient ( err ) ) => { if self . unvalidated_for_too_long ( pool_reader , & proposal . get_id ( ) ) { warn ! ( every_n_seconds LOG_EVERY_N_SECONDS self log " " err ) ; } } } } else { warn ! ( self log " " proposal ) ; change_set . push ( ChangeAction :: HandleInvalid ( proposal . clone ( ) . into_message ( ) , format ! ( " " proposal content get_hash ( ) proposal as_ref ( ) payload get_hash ( ) proposal as_ref ( ) payload as_ref ( ) ) , ) ) } } self . metrics . observe_and_reset_dkg_time_per_validator_run ( ) ; change_set }
Return a `ChangeSet` containing status updates concerning any currently
unvalidated blocks that can now be marked valid or invalid.
Return a ` ChangeSet ` containing status updates concerning any currently unvalidated blocks that can now be marked valid or invalid .
&self
pool_reader
&PoolReader<'_>
&self
pool_reader
&PoolReader<'_>