Repository: paritytech/substrate
File: frame/state-trie-migration/src/lib.rs (Rust)

Code before:
						child: task.dyn_child_items,
						compute: MigrationCompute::Auto,
					});
				}

				MigrationProcess::<T>::put(task);

				weight
			} else {
				T::DbWeight::get().reads(1)
			}
		}
	}

	impl<T: Config> Pallet<T> {
		/// The real weight of a migration of the given number of `items` with total `size`.
		fn dynamic_weight(items: u32, size: u32) -> frame_support::pallet_prelude::Weight {
			let items = items as Weight;
			items
				.saturating_mul(<T as frame_system::Config>::DbWeight::get().reads_writes(1, 1))
				// we assume that the read/write per-byte weight is the same for child and top tree.
				.saturating_add(T::WeightInfo::process_top_key(size))
		}

		/// Put a stop to all ongoing migrations and logs an error.
		fn halt<E: std::fmt::Debug + ?Sized>(msg: &E) {
			log!(error, "migration halted due to: {:?}", msg);
			AutoLimits::<T>::kill();
			Self::deposit_event(Event::<T>::Halted);
		}

		/// Convert a child root key, aka. "Child-bearing top key" into the proper format.
		fn transform_child_key(root: &Vec<u8>) -> Option<&[u8]> {
			use sp_core::storage::{ChildType, PrefixedStorageKey};
			match ChildType::from_prefixed_key(PrefixedStorageKey::new_ref(root)) {
				Some((ChildType::ParentKeyId, root)) => Some(root),
				_ => None,
			}
		}

		/// Same as [`child_io_key`], and it halts the auto/unsigned migrations if a bad child root
		/// is used.
		///
		/// This should be used when we are sure that `root` is a correct default child root.
		fn transform_child_key_or_halt(root: &Vec<u8>) -> &[u8] {
			let key = Self::transform_child_key(root);
			if key.is_none() {
				Self::halt("bad child root key");
			}
			key.unwrap_or_default()
		}

Review comment (bug):
```suggestion
		fn halt<E: sp_std::fmt::Debug + ?Sized>(msg: &E) {
```

Code after:
			if let Some(limits) = Self::auto_limits() {
				let mut task = Self::migration_process();
				if let Err(e) = task.migrate_until_exhaustion(limits) {
					Self::halt(&e);
				}
				let weight = Self::dynamic_weight(task.dyn_total_items(), task.dyn_size);

				log!(
					info,
					"migrated {} top keys, {} child keys, and a total of {} bytes.",
					task.dyn_top_items,
					task.dyn_child_items,
					task.dyn_size,
				);

				if task.finished() {
					Self::deposit_event(Event::<T>::AutoMigrationFinished);
					AutoLimits::<T>::kill();
				} else {
					Self::deposit_event(Event::<T>::Migrated {
						top: task.dyn_top_items,
						child: task.dyn_child_items,
						compute: MigrationCompute::Auto,
					});
				}

				MigrationProcess::<T>::put(task);

				weight
			} else {
				T::DbWeight::get().reads(1)
			}
		}
	}

	impl<T: Config> Pallet<T> {
		/// The real weight of a migration of the given number of `items` with total `size`.
		fn dynamic_weight(items: u32, size: u32) -> frame_support::pallet_prelude::Weight {
			let items = items as Weight;
			items
				.saturating_mul(<T as frame_system::Config>::DbWeight::get().reads_writes(1, 1))
				// we assume that the read/write per-byte weight is the same for child and top tree.
				.saturating_add(T::WeightInfo::process_top_key(size))
		}

		/// Put a stop to all ongoing migrations and logs an error.
		fn halt<E: sp_std::fmt::Debug + ?Sized>(msg: &E) {
			log!(error, "migration halted due to: {:?}", msg);
			AutoLimits::<T>::kill();
			Self::deposit_event(Event::<T>::Halted);
		}