Repository: paritytech/substrate
File: frame/authorship/src/lib.rs (Rust)

Code before:
			return Err(Error::<T>::OldUncle.into())
		}

		let duplicate = existing_uncles.into_iter().any(|h| *h == hash);
		let in_chain = <frame_system::Pallet<T>>::block_hash(uncle.number()) == hash;

		if duplicate || in_chain {
			return Err(Error::<T>::UncleAlreadyIncluded.into())
		}

		// check uncle validity.
		T::FilterUncle::filter_uncle(uncle, accumulator).map_err(Into::into)
	}

	fn prune_old_uncles(minimum_height: T::BlockNumber) {
		let uncles = <Uncles<T>>::get();
		let prune_entries = uncles.iter().take_while(|item| match item {
			UncleEntryItem::Uncle(_, _) => true,
			UncleEntryItem::InclusionHeight(height) => height < &minimum_height,
		});
		let prune_index = prune_entries.count();
		let pruned_uncles =
			<BoundedSlice<'_, _, MaxUncleEntryItems<T>>>::try_from(&uncles[prune_index..])
				.expect("after pruning we can't end up with more uncles than we started with");

		<Uncles<T>>::put(pruned_uncles);
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use crate as pallet_authorship;
	use frame_support::{
		parameter_types,
		traits::{ConstU32, ConstU64, OnFinalize, OnInitialize},
		ConsensusEngineId,
	};
	use sp_core::H256;
	use sp_runtime::{
		generic::DigestItem,
		testing::Header,
		traits::{BlakeTwo256, IdentityLookup},
	};

	type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
	type Block = frame_system::mocking::MockBlock<Test>;

	frame_support::construct_runtime!(
		pub enum Test where
			Block = Block,

Review comment (suggestion):
If for whatever reason the `uncles` in storage was greater than the bound (e.g. when we migrate to a bounded version), then this would panic. Best to use `defensive_proof` here and return an Error.

Code after:

		if uncle.number() < &minimum_height {
			return Err(Error::<T>::OldUncle.into())
		}

		let duplicate = existing_uncles.into_iter().any(|h| *h == hash);
		let in_chain = <frame_system::Pallet<T>>::block_hash(uncle.number()) == hash;

		if duplicate || in_chain {
			return Err(Error::<T>::UncleAlreadyIncluded.into())
		}

		// check uncle validity.
		T::FilterUncle::filter_uncle(uncle, accumulator).map_err(Into::into)
	}

	fn prune_old_uncles(minimum_height: T::BlockNumber) {
		let uncles = <Uncles<T>>::get();
		let prune_entries = uncles.iter().take_while(|item| match item {
			UncleEntryItem::Uncle(_, _) => true,
			UncleEntryItem::InclusionHeight(height) => height < &minimum_height,
		});
		let prune_index = prune_entries.count();
		let pruned_uncles =
			<BoundedSlice<'_, _, MaxUncleEntryItems<T>>>::try_from(&uncles[prune_index..])
				.expect("after pruning we can't end up with more uncles than we started with");

		<Uncles<T>>::put(pruned_uncles);
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use crate as pallet_authorship;
	use frame_support::{
		parameter_types,
		traits::{ConstU32, ConstU64, OnFinalize, OnInitialize},
		ConsensusEngineId,
	};
	use sp_core::H256;
	use sp_runtime::{
		generic::DigestItem,
		testing::Header,
		traits::{BlakeTwo256, IdentityLookup},
	};

	type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
	type Block = frame_system::mocking::MockBlock<Test>;

	frame_support::construct_runtime!(