Repository: paritytech/substrate
File: frame/message-queue/src/lib.rs (Rust)

Code before:
		ItemExecutionStatus::Executed(is_processed)
	}

	/// Ensure the correctness of state of this pallet.
	///
	/// # Assumptions-
	///
	/// If `serviceHead` points to a ready Queue, then BookState of that Queue has:
	///
	/// * `message_count` > 0
	/// * `size` > 0
	/// * `end` > begin
	/// * Some(ready_neighbours)
	/// * If `ready_neighbours.next` == self.origin, then `ready_neighbours.prev` == self.origin
	///   (only queue in ring)
	///
	/// For Pages(begin to end-1) in BookState:
	///
	/// * `remaining` > 0
	/// * `remaining_size` > 0
	/// * `first` <= `last`
	/// * Every page can be decoded into peek_* functions

	pub fn do_try_state() -> Result<(), &'static str> {
		// No state to check
		if ServiceHead::<T>::get().is_none() {
			return Ok(())
		}

		//loop around this origin
		let starting_origin = ServiceHead::<T>::get().unwrap();

		let mut service_head = ServiceHead::<T>::get();

		loop {
			if let Some(head) = service_head {
				let head_book_state = BookStateFor::<T>::get(&head);
				assert!(
					head_book_state.message_count > 0,
					"There must be some messages if in ReadyRing"
				);
				assert!(head_book_state.size > 0, "There must be some messages if in ReadyRing");
				assert!(
					head_book_state.end > head_book_state.begin,
					"End > Begin if unprocessed messages exists"
				);
				assert!(
					head_book_state.ready_neighbours.is_some(),
					"There must be neighbours if in ReadyRing"
				);


Review comment (suggestion):
There are some more basic assumption as well, like that no map is corrupted.  
To check this you can do `Map::iter_keys().count() == Map::iter_values().count()` for all storage maps in the pallet.

Code after:
		use MessageExecutionStatus::*;
		let is_processed = match Self::process_message_payload(
			origin.clone(),
			page_index,
			page.first_index,
			payload.deref(),
			weight,
			overweight_limit,
		) {
			InsufficientWeight => return ItemExecutionStatus::Bailed,
			Unprocessable { permanent: false } => return ItemExecutionStatus::NoProgress,
			Processed | Unprocessable { permanent: true } => true,
			Overweight => false,
		};

		if is_processed {
			book_state.message_count.saturating_dec();
			book_state.size.saturating_reduce(payload.len() as u64);
		}
		page.skip_first(is_processed);
		ItemExecutionStatus::Executed(is_processed)
	}

	/// Ensure the correctness of state of this pallet.
	///
	/// # Assumptions-
	///
	/// If `serviceHead` points to a ready Queue, then BookState of that Queue has:
	///
	/// * `message_count` > 0
	/// * `size` > 0
	/// * `end` > `begin`
	/// * Some(ready_neighbours)
	/// * If `ready_neighbours.next` == self.origin, then `ready_neighbours.prev` == self.origin
	///   (only queue in ring)
	///
	/// For Pages(begin to end-1) in BookState:
	///
	/// * `remaining` > 0
	/// * `remaining_size` > 0
	/// * `first` <= `last`
	/// * Every page can be decoded into peek_* functions
	#[cfg(any(test, feature = "try-runtime"))]
	pub fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> {
		// Checking memory corruption for BookStateFor
		ensure!(
			BookStateFor::<T>::iter_keys().count() == BookStateFor::<T>::iter_values().count(),
			"Memory Corruption in BookStateFor"
		);
		// Checking memory corruption for Pages
		ensure!(