Skip to main content

topsoil_core/traits/
misc.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Smaller traits used in FRAME which don't need their own file.
8
9use crate::dispatch::{DispatchResult, Parameter};
10use alloc::{vec, vec::Vec};
11use codec::{CompactLen, Decode, DecodeLimit, Encode, EncodeLike, Input, MaxEncodedLen};
12use impl_trait_for_tuples::impl_for_tuples;
13use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
14use subsoil::arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, One, Saturating};
15use subsoil::core::bounded::bounded_vec::TruncateFrom;
16
17use core::cmp::Ordering;
18#[doc(hidden)]
19pub use subsoil::runtime::traits::{
20	ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstInt, ConstU128, ConstU16,
21	ConstU32, ConstU64, ConstU8, ConstUint, Get, GetDefault, TryCollect, TypedGet,
22};
23use subsoil::runtime::{
24	traits::{Block as BlockT, ExtrinsicCall},
25	DispatchError,
26};
27
28#[doc(hidden)]
29pub const DEFENSIVE_OP_PUBLIC_ERROR: &str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/polkadot-sdk/issues";
30#[doc(hidden)]
31pub const DEFENSIVE_OP_INTERNAL_ERROR: &str = "Defensive failure has been triggered!";
32
33/// Trait to get the number of variants in any enum.
34pub trait VariantCount {
35	/// Get the number of variants.
36	const VARIANT_COUNT: u32;
37}
38
39impl VariantCount for () {
40	const VARIANT_COUNT: u32 = 0;
41}
42
43impl VariantCount for u8 {
44	const VARIANT_COUNT: u32 = 256;
45}
46
47/// Adapter for `Get<u32>` to access `VARIANT_COUNT` from `trait pub trait VariantCount {`.
48pub struct VariantCountOf<T: VariantCount>(core::marker::PhantomData<T>);
49impl<T: VariantCount> Get<u32> for VariantCountOf<T> {
50	fn get() -> u32 {
51		T::VARIANT_COUNT
52	}
53}
54
55/// Generic function to mark an execution path as ONLY defensive.
56///
57/// Similar to mark a match arm or `if/else` branch as `unreachable!`.
58#[macro_export]
59macro_rules! defensive {
60	() => {
61		$crate::__private::log::error!(
62			target: "runtime::defensive",
63			"{}",
64			$crate::traits::DEFENSIVE_OP_PUBLIC_ERROR
65		);
66		debug_assert!(false, "{}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR);
67	};
68	($error:expr $(,)?) => {
69		$crate::__private::log::error!(
70			target: "runtime::defensive",
71			"{}: {:?}",
72			$crate::traits::DEFENSIVE_OP_PUBLIC_ERROR,
73			$error
74		);
75		debug_assert!(false, "{}: {:?}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR, $error);
76	};
77	($error:expr, $proof:expr $(,)?) => {
78		$crate::__private::log::error!(
79			target: "runtime::defensive",
80			"{}: {:?}: {:?}",
81			$crate::traits::DEFENSIVE_OP_PUBLIC_ERROR,
82			$error,
83			$proof,
84		);
85		debug_assert!(false, "{}: {:?}: {:?}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR, $error, $proof);
86	}
87}
88
89/// Trigger a defensive failure if a condition is not met.
90///
91/// Similar to [`assert!`] but will print an error without `debug_assertions` instead of silently
92/// ignoring it. Only accepts one instead of variable formatting arguments.
93///
94/// # Example
95///
96/// ```should_panic
97/// topsoil_core::defensive_assert!(1 == 0, "Must fail")
98/// ```
99#[macro_export]
100macro_rules! defensive_assert {
101	($cond:expr $(, $proof:expr )? $(,)?) => {
102		if !($cond) {
103			$crate::defensive!(::core::stringify!($cond) $(, $proof )?);
104		}
105	};
106}
107
108/// Prelude module for all defensive traits to be imported at once.
109pub mod defensive_prelude {
110	pub use super::{Defensive, DefensiveOption, DefensiveResult};
111}
112
113/// A trait to handle errors and options when you are really sure that a condition must hold, but
114/// not brave enough to `expect` on it, or a default fallback value makes more sense.
115///
116/// This trait mostly focuses on methods that eventually unwrap the inner value. See
117/// [`DefensiveResult`] and [`DefensiveOption`] for methods that specifically apply to the
118/// respective types.
119///
120/// Each function in this trait will have two side effects, aside from behaving exactly as the name
121/// would suggest:
122///
123/// 1. It panics on `#[debug_assertions]`, so if the infallible code is reached in any of the tests,
124///    you realize.
125/// 2. It will log an error using the runtime logging system. This might help you detect such bugs
126///    in production as well. Note that the log message, as of now, are not super expressive. Your
127///    best shot of fully diagnosing the error would be to infer the block number of which the log
128///    message was emitted, then re-execute that block using `check-block` or `try-runtime`
129///    subcommands in substrate client.
130pub trait Defensive<T> {
131	/// Exactly the same as `unwrap_or`, but it does the defensive warnings explained in the trait
132	/// docs.
133	fn defensive_unwrap_or(self, other: T) -> T;
134
135	/// Exactly the same as `unwrap_or_else`, but it does the defensive warnings explained in the
136	/// trait docs.
137	fn defensive_unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T;
138
139	/// Exactly the same as `unwrap_or_default`, but it does the defensive warnings explained in the
140	/// trait docs.
141	fn defensive_unwrap_or_default(self) -> T
142	where
143		T: Default;
144
145	/// Does not alter the inner value at all, but it will log warnings if the inner value is `None`
146	/// or `Err`.
147	///
148	/// In some ways, this is like  `.defensive_map(|x| x)`.
149	///
150	/// This is useful as:
151	/// ```nocompile
152	/// if let Some(inner) = maybe_value().defensive() {
153	/// 	 	..
154	/// }
155	/// ```
156	fn defensive(self) -> Self;
157
158	/// Same as [`Defensive::defensive`], but it takes a proof as input, and displays it if the
159	/// defensive operation has been triggered.
160	fn defensive_proof(self, proof: &'static str) -> Self;
161}
162
163/// Subset of methods similar to [`Defensive`] that can only work for a `Result`.
164pub trait DefensiveResult<T, E> {
165	/// Defensively map the error into another return type, but you are really sure that this
166	/// conversion should never be needed.
167	fn defensive_map_err<F, O: FnOnce(E) -> F>(self, o: O) -> Result<T, F>;
168
169	/// Defensively map and unpack the value to something else (`U`), or call the default callback
170	/// if `Err`, which should never happen.
171	fn defensive_map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U;
172
173	/// Defensively transform this result into an option, discarding the `Err` variant if it
174	/// happens, which should never happen.
175	fn defensive_ok(self) -> Option<T>;
176
177	/// Exactly the same as `map`, but it prints the appropriate warnings if the value being mapped
178	/// is `Err`.
179	fn defensive_map<U, F: FnOnce(T) -> U>(self, f: F) -> Result<U, E>;
180}
181
182/// Subset of methods similar to [`Defensive`] that can only work for a `Option`.
183pub trait DefensiveOption<T> {
184	/// Potentially map and unpack the value to something else (`U`), or call the default callback
185	/// if `None`, which should never happen.
186	fn defensive_map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U;
187
188	/// Defensively transform this option to a result, mapping `None` to the return value of an
189	/// error closure.
190	fn defensive_ok_or_else<E: core::fmt::Debug, F: FnOnce() -> E>(self, err: F) -> Result<T, E>;
191
192	/// Defensively transform this option to a result, mapping `None` to a default value.
193	fn defensive_ok_or<E: core::fmt::Debug>(self, err: E) -> Result<T, E>;
194
195	/// Exactly the same as `map`, but it prints the appropriate warnings if the value being mapped
196	/// is `None`.
197	fn defensive_map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U>;
198}
199
200impl<T> Defensive<T> for Option<T> {
201	fn defensive_unwrap_or(self, or: T) -> T {
202		match self {
203			Some(inner) => inner,
204			None => {
205				defensive!();
206				or
207			},
208		}
209	}
210
211	fn defensive_unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
212		match self {
213			Some(inner) => inner,
214			None => {
215				defensive!();
216				f()
217			},
218		}
219	}
220
221	fn defensive_unwrap_or_default(self) -> T
222	where
223		T: Default,
224	{
225		match self {
226			Some(inner) => inner,
227			None => {
228				defensive!();
229				Default::default()
230			},
231		}
232	}
233
234	fn defensive(self) -> Self {
235		match self {
236			Some(inner) => Some(inner),
237			None => {
238				defensive!();
239				None
240			},
241		}
242	}
243
244	fn defensive_proof(self, proof: &'static str) -> Self {
245		if self.is_none() {
246			defensive!(proof);
247		}
248		self
249	}
250}
251
252impl<T, E: core::fmt::Debug> Defensive<T> for Result<T, E> {
253	fn defensive_unwrap_or(self, or: T) -> T {
254		match self {
255			Ok(inner) => inner,
256			Err(e) => {
257				defensive!(e);
258				or
259			},
260		}
261	}
262
263	fn defensive_unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
264		match self {
265			Ok(inner) => inner,
266			Err(e) => {
267				defensive!(e);
268				f()
269			},
270		}
271	}
272
273	fn defensive_unwrap_or_default(self) -> T
274	where
275		T: Default,
276	{
277		match self {
278			Ok(inner) => inner,
279			Err(e) => {
280				defensive!(e);
281				Default::default()
282			},
283		}
284	}
285
286	fn defensive(self) -> Self {
287		match self {
288			Ok(inner) => Ok(inner),
289			Err(e) => {
290				defensive!(e);
291				Err(e)
292			},
293		}
294	}
295
296	fn defensive_proof(self, proof: &'static str) -> Self {
297		match self {
298			Ok(inner) => Ok(inner),
299			Err(e) => {
300				defensive!(e, proof);
301				Err(e)
302			},
303		}
304	}
305}
306
307impl<T, E: core::fmt::Debug> DefensiveResult<T, E> for Result<T, E> {
308	fn defensive_map_err<F, O: FnOnce(E) -> F>(self, o: O) -> Result<T, F> {
309		self.map_err(|e| {
310			defensive!(e);
311			o(e)
312		})
313	}
314
315	fn defensive_map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
316		self.map_or_else(
317			|e| {
318				defensive!(e);
319				default(e)
320			},
321			f,
322		)
323	}
324
325	fn defensive_ok(self) -> Option<T> {
326		match self {
327			Ok(inner) => Some(inner),
328			Err(e) => {
329				defensive!(e);
330				None
331			},
332		}
333	}
334
335	fn defensive_map<U, F: FnOnce(T) -> U>(self, f: F) -> Result<U, E> {
336		match self {
337			Ok(inner) => Ok(f(inner)),
338			Err(e) => {
339				defensive!(e);
340				Err(e)
341			},
342		}
343	}
344}
345
346impl<T> DefensiveOption<T> for Option<T> {
347	fn defensive_map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
348		self.map_or_else(
349			|| {
350				defensive!();
351				default()
352			},
353			f,
354		)
355	}
356
357	fn defensive_ok_or_else<E: core::fmt::Debug, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
358		self.ok_or_else(|| {
359			let err_value = err();
360			defensive!(err_value);
361			err_value
362		})
363	}
364
365	fn defensive_ok_or<E: core::fmt::Debug>(self, err: E) -> Result<T, E> {
366		self.ok_or_else(|| {
367			defensive!(err);
368			err
369		})
370	}
371
372	fn defensive_map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
373		match self {
374			Some(inner) => Some(f(inner)),
375			None => {
376				defensive!();
377				None
378			},
379		}
380	}
381}
382
383/// A variant of [`Defensive`] with the same rationale, for the arithmetic operations where in
384/// case an infallible operation fails, it saturates.
385pub trait DefensiveSaturating {
386	/// Return `self` plus `other` defensively.
387	fn defensive_saturating_add(self, other: Self) -> Self;
388	/// Return `self` minus `other` defensively.
389	fn defensive_saturating_sub(self, other: Self) -> Self;
390	/// Return the product of `self` and `other` defensively.
391	fn defensive_saturating_mul(self, other: Self) -> Self;
392	/// Increase `self` by `other` defensively.
393	fn defensive_saturating_accrue(&mut self, other: Self);
394	/// Reduce `self` by `other` defensively.
395	fn defensive_saturating_reduce(&mut self, other: Self);
396	/// Increment `self` by one defensively.
397	fn defensive_saturating_inc(&mut self);
398	/// Decrement `self` by one defensively.
399	fn defensive_saturating_dec(&mut self);
400}
401
402// NOTE: A bit unfortunate, since T has to be bound by all the traits needed. Could make it
403// `DefensiveSaturating<T>` to mitigate.
404impl<T: Saturating + CheckedAdd + CheckedMul + CheckedSub + One> DefensiveSaturating for T {
405	fn defensive_saturating_add(self, other: Self) -> Self {
406		self.checked_add(&other).defensive_unwrap_or_else(|| self.saturating_add(other))
407	}
408	fn defensive_saturating_sub(self, other: Self) -> Self {
409		self.checked_sub(&other).defensive_unwrap_or_else(|| self.saturating_sub(other))
410	}
411	fn defensive_saturating_mul(self, other: Self) -> Self {
412		self.checked_mul(&other).defensive_unwrap_or_else(|| self.saturating_mul(other))
413	}
414	fn defensive_saturating_accrue(&mut self, other: Self) {
415		// Use `replace` here since `take` would require `T: Default`.
416		*self = core::mem::replace(self, One::one()).defensive_saturating_add(other);
417	}
418	fn defensive_saturating_reduce(&mut self, other: Self) {
419		// Use `replace` here since `take` would require `T: Default`.
420		*self = core::mem::replace(self, One::one()).defensive_saturating_sub(other);
421	}
422	fn defensive_saturating_inc(&mut self) {
423		self.defensive_saturating_accrue(One::one());
424	}
425	fn defensive_saturating_dec(&mut self) {
426		self.defensive_saturating_reduce(One::one());
427	}
428}
429
430/// Construct an object by defensively truncating an input if the `TryFrom` conversion fails.
431pub trait DefensiveTruncateFrom<T> {
432	/// Use `TryFrom` first and defensively fall back to truncating otherwise.
433	///
434	/// # Example
435	///
436	/// ```
437	/// use topsoil_core::{BoundedVec, traits::DefensiveTruncateFrom};
438	/// use subsoil::runtime::traits::ConstU32;
439	///
440	/// let unbound = vec![1, 2];
441	/// let bound = BoundedVec::<u8, ConstU32<2>>::defensive_truncate_from(unbound);
442	///
443	/// assert_eq!(bound, vec![1, 2]);
444	/// ```
445	fn defensive_truncate_from(unbound: T) -> Self;
446}
447
448impl<T, U> DefensiveTruncateFrom<U> for T
449where
450	// NOTE: We use the fact that `BoundedVec` and
451	// `BoundedSlice` use `Self` as error type. We could also
452	// require a `Clone` bound and use `unbound.clone()` in the
453	// error case.
454	T: TruncateFrom<U> + TryFrom<U, Error = U>,
455{
456	fn defensive_truncate_from(unbound: U) -> Self {
457		unbound.try_into().map_or_else(
458			|err| {
459				defensive!("DefensiveTruncateFrom truncating");
460				T::truncate_from(err)
461			},
462			|bound| bound,
463		)
464	}
465}
466
467/// Defensively truncate a value and convert it into its bounded form.
468pub trait DefensiveTruncateInto<T> {
469	/// Defensively truncate a value and convert it into its bounded form.
470	fn defensive_truncate_into(self) -> T;
471}
472
473impl<T, U: DefensiveTruncateFrom<T>> DefensiveTruncateInto<U> for T {
474	fn defensive_truncate_into(self) -> U {
475		U::defensive_truncate_from(self)
476	}
477}
478/// Defensively calculates the minimum of two values.
479///
480/// Can be used in contexts where we assume the receiver value to be (strictly) smaller.
481pub trait DefensiveMin<T> {
482	/// Returns the minimum and defensively checks that `self` is not larger than `other`.
483	///
484	/// # Example
485	///
486	/// ```
487	/// use topsoil_core::traits::DefensiveMin;
488	/// // min(3, 4) is 3.
489	/// assert_eq!(3, 3_u32.defensive_min(4_u32));
490	/// // min(4, 4) is 4.
491	/// assert_eq!(4, 4_u32.defensive_min(4_u32));
492	/// ```
493	///
494	/// ```ignore
495	/// use topsoil_core::traits::DefensiveMin;
496	/// // min(4, 3) triggers a defensive failure in debug builds and returns 3 in release.
497	/// 4_u32.defensive_min(3_u32);
498	/// ```
499	fn defensive_min(self, other: T) -> Self;
500
501	/// Returns the minimum and defensively checks that `self` is smaller than `other`.
502	///
503	/// # Example
504	///
505	/// ```
506	/// use topsoil_core::traits::DefensiveMin;
507	/// // min(3, 4) is 3.
508	/// assert_eq!(3, 3_u32.defensive_strict_min(4_u32));
509	/// ```
510	///
511	/// ```ignore
512	/// use topsoil_core::traits::DefensiveMin;
513	/// // min(4, 4) triggers a defensive failure in debug builds and returns 4 in release.
514	/// 4_u32.defensive_strict_min(4_u32);
515	/// ```
516	fn defensive_strict_min(self, other: T) -> Self;
517}
518
519impl<T> DefensiveMin<T> for T
520where
521	T: PartialOrd<T>,
522{
523	fn defensive_min(self, other: T) -> Self {
524		if self <= other {
525			self
526		} else {
527			defensive!("DefensiveMin");
528			other
529		}
530	}
531
532	fn defensive_strict_min(self, other: T) -> Self {
533		if self < other {
534			self
535		} else {
536			defensive!("DefensiveMin strict");
537			other
538		}
539	}
540}
541
542/// Defensively calculates the maximum of two values.
543///
544/// Can be used in contexts where we assume the receiver value to be (strictly) larger.
545pub trait DefensiveMax<T> {
546	/// Returns the maximum and defensively asserts that `other` is not larger than `self`.
547	///
548	/// # Example
549	///
550	/// ```
551	/// use topsoil_core::traits::DefensiveMax;
552	/// // max(4, 3) is 4.
553	/// assert_eq!(4, 4_u32.defensive_max(3_u32));
554	/// // max(4, 4) is 4.
555	/// assert_eq!(4, 4_u32.defensive_max(4_u32));
556	/// ```
557	///
558	/// ```ignore
559	/// use topsoil_core::traits::DefensiveMax;
560	/// // max(4, 5) triggers a defensive failure in debug builds and returns 5 in release.
561	/// 4_u32.defensive_max(5_u32);
562	/// ```
563	fn defensive_max(self, other: T) -> Self;
564
565	/// Returns the maximum and defensively asserts that `other` is smaller than `self`.
566	///
567	/// # Example
568	///
569	/// ```
570	/// use topsoil_core::traits::DefensiveMax;
571	/// // y(4, 3) is 4.
572	/// assert_eq!(4, 4_u32.defensive_strict_max(3_u32));
573	/// ```
574	///
575	/// ```ignore
576	/// use topsoil_core::traits::DefensiveMax;
577	/// // max(4, 4) triggers a defensive failure in debug builds and returns 4 in release.
578	/// 4_u32.defensive_strict_max(4_u32);
579	/// ```
580	fn defensive_strict_max(self, other: T) -> Self;
581}
582
583impl<T> DefensiveMax<T> for T
584where
585	T: PartialOrd<T>,
586{
587	fn defensive_max(self, other: T) -> Self {
588		if self >= other {
589			self
590		} else {
591			defensive!("DefensiveMax");
592			other
593		}
594	}
595
596	fn defensive_strict_max(self, other: T) -> Self {
597		if self > other {
598			self
599		} else {
600			defensive!("DefensiveMax strict");
601			other
602		}
603	}
604}
605
606/// Anything that can have a `::len()` method.
607pub trait Len {
608	/// Return the length of data type.
609	fn len(&self) -> usize;
610}
611
612impl<T: IntoIterator + Clone> Len for T
613where
614	<T as IntoIterator>::IntoIter: ExactSizeIterator,
615{
616	fn len(&self) -> usize {
617		self.clone().into_iter().len()
618	}
619}
620
621/// A type for which some values make sense to be able to drop without further consideration.
622pub trait TryDrop: Sized {
623	/// Drop an instance cleanly. Only works if its value represents "no-operation".
624	fn try_drop(self) -> Result<(), Self>;
625}
626
627impl TryDrop for () {
628	fn try_drop(self) -> Result<(), Self> {
629		Ok(())
630	}
631}
632
633/// Return type used when we need to return one of two items, each of the opposite direction or
634/// sign, with one (`Same`) being of the same type as the `self` or primary argument of the function
635/// that returned it.
636pub enum SameOrOther<A, B> {
637	/// No item.
638	None,
639	/// An item of the same type as the `Self` on which the return function was called.
640	Same(A),
641	/// An item of the opposite type to the `Self` on which the return function was called.
642	Other(B),
643}
644
645impl<A, B> TryDrop for SameOrOther<A, B> {
646	fn try_drop(self) -> Result<(), Self> {
647		if let SameOrOther::None = self {
648			Ok(())
649		} else {
650			Err(self)
651		}
652	}
653}
654
655impl<A, B> SameOrOther<A, B> {
656	/// Returns `Ok` with the inner value of `Same` if `self` is that, otherwise returns `Err` with
657	/// `self`.
658	pub fn try_same(self) -> Result<A, Self> {
659		match self {
660			SameOrOther::Same(a) => Ok(a),
661			x => Err(x),
662		}
663	}
664
665	/// Returns `Ok` with the inner value of `Other` if `self` is that, otherwise returns `Err` with
666	/// `self`.
667	pub fn try_other(self) -> Result<B, Self> {
668		match self {
669			SameOrOther::Other(b) => Ok(b),
670			x => Err(x),
671		}
672	}
673
674	/// Returns `Ok` if `self` is `None`, otherwise returns `Err` with `self`.
675	pub fn try_none(self) -> Result<(), Self> {
676		match self {
677			SameOrOther::None => Ok(()),
678			x => Err(x),
679		}
680	}
681
682	pub fn same(self) -> Result<A, B>
683	where
684		A: Default,
685	{
686		match self {
687			SameOrOther::Same(a) => Ok(a),
688			SameOrOther::None => Ok(A::default()),
689			SameOrOther::Other(b) => Err(b),
690		}
691	}
692
693	pub fn other(self) -> Result<B, A>
694	where
695		B: Default,
696	{
697		match self {
698			SameOrOther::Same(a) => Err(a),
699			SameOrOther::None => Ok(B::default()),
700			SameOrOther::Other(b) => Ok(b),
701		}
702	}
703}
704
705/// Handler for when a new account has been created.
706#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
707#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
708#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
709pub trait OnNewAccount<AccountId> {
710	/// A new account `who` has been registered.
711	fn on_new_account(who: &AccountId);
712}
713
714/// The account with the given id was reaped.
715#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
716#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
717#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
718pub trait OnKilledAccount<AccountId> {
719	/// The account with the given id was reaped.
720	fn on_killed_account(who: &AccountId);
721}
722
723/// A simple, generic one-parameter event notifier/handler.
724pub trait HandleLifetime<T> {
725	/// An account was created.
726	fn created(_t: &T) -> Result<(), DispatchError> {
727		Ok(())
728	}
729
730	/// An account was killed.
731	fn killed(_t: &T) -> Result<(), DispatchError> {
732		Ok(())
733	}
734}
735
736impl<T> HandleLifetime<T> for () {}
737
738pub trait Time {
739	type Moment: subsoil::arithmetic::traits::AtLeast32Bit
740		+ Parameter
741		+ Default
742		+ Copy
743		+ MaxEncodedLen;
744
745	fn now() -> Self::Moment;
746}
747
748/// Trait to deal with unix time.
749pub trait UnixTime {
750	/// Return duration since `SystemTime::UNIX_EPOCH`.
751	fn now() -> core::time::Duration;
752}
753
754/// Trait to be used when types are exactly same.
755///
756/// This allow to convert back and forth from type, a reference and a mutable reference.
757pub trait IsType<T>: Into<T> + From<T> {
758	/// Cast reference.
759	fn from_ref(t: &T) -> &Self;
760
761	/// Cast reference.
762	fn into_ref(&self) -> &T;
763
764	/// Cast mutable reference.
765	fn from_mut(t: &mut T) -> &mut Self;
766
767	/// Cast mutable reference.
768	fn into_mut(&mut self) -> &mut T;
769}
770
771impl<T> IsType<T> for T {
772	fn from_ref(t: &T) -> &Self {
773		t
774	}
775	fn into_ref(&self) -> &T {
776		self
777	}
778	fn from_mut(t: &mut T) -> &mut Self {
779		t
780	}
781	fn into_mut(&mut self) -> &mut T {
782		self
783	}
784}
785
786/// Something that can be checked to be a of sub type `T`.
787///
788/// This is useful for enums where each variant encapsulates a different sub type, and
789/// you need access to these sub types.
790///
791/// For example, in FRAME, this trait is implemented for the runtime `Call` enum. Pallets use this
792/// to check if a certain call is an instance of the local pallet's `Call` enum.
793///
794/// # Example
795///
796/// ```
797/// # use topsoil_core::traits::IsSubType;
798///
799/// enum Test {
800///     String(String),
801///     U32(u32),
802/// }
803///
804/// impl IsSubType<String> for Test {
805///     fn is_sub_type(&self) -> Option<&String> {
806///         match self {
807///             Self::String(ref r) => Some(r),
808///             _ => None,
809///         }
810///     }
811/// }
812///
813/// impl IsSubType<u32> for Test {
814///     fn is_sub_type(&self) -> Option<&u32> {
815///         match self {
816///             Self::U32(ref r) => Some(r),
817///             _ => None,
818///         }
819///     }
820/// }
821///
822/// fn main() {
823///     let data = Test::String("test".into());
824///
825///     assert_eq!("test", IsSubType::<String>::is_sub_type(&data).unwrap().as_str());
826/// }
827/// ```
828pub trait IsSubType<T> {
829	/// Returns `Some(_)` if `self` is an instance of sub type `T`.
830	fn is_sub_type(&self) -> Option<&T>;
831}
832
833/// Something that can execute a given block.
834///
835/// Executing a block means that all extrinsics in a given block will be executed and the resulting
836/// header will be checked against the header of the given block.
837pub trait ExecuteBlock<Block: BlockT> {
838	/// Execute the given `block`.
839	///
840	/// This will execute all extrinsics in the block and check that the resulting header is
841	/// correct.
842	///
843	/// This function is a wrapper around [`Self::verify_and_remove_seal`] and
844	/// [`Self::execute_verified_block`].
845	///
846	/// # Panic
847	///
848	/// Panics when an extrinsics panics or the resulting header doesn't match the expected header
849	/// or the seal is invalid.
850	fn execute_block(mut block: Block::LazyBlock) {
851		Self::verify_and_remove_seal(&mut block);
852		Self::execute_verified_block(block);
853	}
854
855	/// Verify and remove seal.
856	///
857	/// Verifies any seal meant for the consensus logic represented by the implementation. An
858	/// implementation may also chooses to not verify anything.
859	///
860	/// # Panic
861	///
862	/// Panics if a seal is invalid or if a seal is required, but not present.
863	fn verify_and_remove_seal(block: &mut Block::LazyBlock);
864
865	/// Executes the given `block` after it was verified by `[Self::verify_and_remove_seal]`.
866	///
867	/// # Panic
868	///
869	/// Panics when an extrinsics panics or the resulting header doesn't match the expected header.
870	fn execute_verified_block(block: Block::LazyBlock);
871}
872
873/// Something that can compare privileges of two origins.
874pub trait PrivilegeCmp<Origin> {
875	/// Compare the `left` to the `right` origin.
876	///
877	/// The returned ordering should be from the pov of the `left` origin.
878	///
879	/// Should return `None` when it can not compare the given origins.
880	fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering>;
881}
882
883/// Implementation of [`PrivilegeCmp`] that only checks for equal origins.
884///
885/// This means it will either return [`Ordering::Equal`] or `None`.
886pub struct EqualPrivilegeOnly;
887impl<Origin: PartialEq> PrivilegeCmp<Origin> for EqualPrivilegeOnly {
888	fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering> {
889		(left == right).then(|| Ordering::Equal)
890	}
891}
892
893/// Off-chain computation trait.
894///
895/// Implementing this trait on a module allows you to perform long-running tasks
896/// that make (by default) validators generate transactions that feed results
897/// of those long-running computations back on chain.
898///
899/// NOTE: This function runs off-chain, so it can access the block state,
900/// but cannot preform any alterations. More specifically alterations are
901/// not forbidden, but they are not persisted in any way after the worker
902/// has finished.
903#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
904#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
905#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
906pub trait OffchainWorker<BlockNumber> {
907	/// This function is being called after every block import (when fully synced).
908	///
909	/// Implement this and use any of the `Offchain` `subsoil::io` set of APIs
910	/// to perform off-chain computations, calls and submit transactions
911	/// with results to trigger any on-chain changes.
912	/// Any state alterations are lost and are not persisted.
913	fn offchain_worker(_n: BlockNumber) {}
914}
915
916/// Some amount of backing from a group. The precise definition of what it means to "back" something
917/// is left flexible.
918pub struct Backing {
919	/// The number of members of the group that back some motion.
920	pub approvals: u32,
921	/// The total count of group members.
922	pub eligible: u32,
923}
924
925/// Retrieve the backing from an object's ref.
926pub trait GetBacking {
927	/// Returns `Some` `Backing` if `self` represents a fractional/groupwise backing of some
928	/// implicit motion. `None` if it does not.
929	fn get_backing(&self) -> Option<Backing>;
930}
931
932/// A trait to check if an extrinsic is an inherent.
933pub trait IsInherent<Extrinsic> {
934	/// Whether this extrinsic is an inherent.
935	fn is_inherent(ext: &Extrinsic) -> bool;
936}
937
938/// Interface for types capable of constructing an inherent extrinsic.
939pub trait InherentBuilder: ExtrinsicCall {
940	/// Create a new inherent from a given call.
941	fn new_inherent(call: Self::Call) -> Self;
942}
943
944impl<Address, Call, Signature, Extra> InherentBuilder
945	for subsoil::runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extra>
946where
947	Address: TypeInfo,
948	Call: TypeInfo,
949	Signature: TypeInfo,
950	Extra: TypeInfo,
951{
952	fn new_inherent(call: Self::Call) -> Self {
953		Self::new_bare(call)
954	}
955}
956
957/// Interface for types capable of constructing a signed transaction.
958pub trait SignedTransactionBuilder: ExtrinsicCall {
959	type Address;
960	type Signature;
961	type Extension;
962
963	/// Create a new signed transaction from a given call and extension using the provided signature
964	/// data.
965	fn new_signed_transaction(
966		call: Self::Call,
967		signed: Self::Address,
968		signature: Self::Signature,
969		tx_ext: Self::Extension,
970	) -> Self;
971}
972
973impl<Address, Call, Signature, Extension> SignedTransactionBuilder
974	for subsoil::runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extension>
975where
976	Address: TypeInfo,
977	Call: TypeInfo,
978	Signature: TypeInfo,
979	Extension: TypeInfo,
980{
981	type Address = Address;
982	type Signature = Signature;
983	type Extension = Extension;
984
985	fn new_signed_transaction(
986		call: Self::Call,
987		signed: Address,
988		signature: Signature,
989		tx_ext: Extension,
990	) -> Self {
991		Self::new_signed(call, signed, signature, tx_ext)
992	}
993}
994
995/// Something that can estimate the fee of a (frame-based) call.
996///
997/// Typically, the same pallet that will charge transaction fees will implement this.
998pub trait EstimateCallFee<Call, Balance> {
999	/// Estimate the fee of this call.
1000	///
1001	/// The dispatch info and the length is deduced from the call. The post info can optionally be
1002	/// provided.
1003	fn estimate_call_fee(call: &Call, post_info: crate::dispatch::PostDispatchInfo) -> Balance;
1004}
1005
1006// Useful for building mocks.
1007#[cfg(feature = "std")]
1008impl<Call, Balance: From<u32>, const T: u32> EstimateCallFee<Call, Balance> for ConstU32<T> {
1009	fn estimate_call_fee(_: &Call, _: crate::dispatch::PostDispatchInfo) -> Balance {
1010		T.into()
1011	}
1012}
1013
1014#[cfg(feature = "std")]
1015impl<Call, Balance: From<u32>, const T: u64> EstimateCallFee<Call, Balance> for ConstU64<T> {
1016	fn estimate_call_fee(_: &Call, _: crate::dispatch::PostDispatchInfo) -> Balance {
1017		(T as u32).into()
1018	}
1019}
1020
1021/// A wrapper for any type `T` which implement encode/decode in a way compatible with `Vec<u8>`.
1022///
1023/// The encoding is the encoding of `T` prepended with the compact encoding of its size in bytes.
1024/// Thus the encoded value can be decoded as a `Vec<u8>`.
1025#[derive(Debug, Eq, PartialEq, Default, Clone)]
1026#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
1027pub struct WrapperOpaque<T>(pub T);
1028
1029impl<T: Encode> EncodeLike for WrapperOpaque<T> {}
1030impl<T: Encode> EncodeLike<WrapperKeepOpaque<T>> for WrapperOpaque<T> {}
1031
1032impl<T: Encode> Encode for WrapperOpaque<T> {
1033	fn size_hint(&self) -> usize {
1034		self.0.size_hint().saturating_add(<codec::Compact<u32>>::max_encoded_len())
1035	}
1036
1037	fn encode_to<O: codec::Output + ?Sized>(&self, dest: &mut O) {
1038		self.0.encode().encode_to(dest);
1039	}
1040
1041	fn encode(&self) -> Vec<u8> {
1042		self.0.encode().encode()
1043	}
1044
1045	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
1046		self.0.encode().using_encoded(f)
1047	}
1048}
1049
1050impl<T: Decode> Decode for WrapperOpaque<T> {
1051	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
1052		Ok(Self(T::decode_all_with_depth_limit(
1053			crate::MAX_EXTRINSIC_DEPTH,
1054			&mut &<Vec<u8>>::decode(input)?[..],
1055		)?))
1056	}
1057
1058	fn skip<I: Input>(input: &mut I) -> Result<(), codec::Error> {
1059		<Vec<u8>>::skip(input)
1060	}
1061}
1062
1063impl<T> From<T> for WrapperOpaque<T> {
1064	fn from(t: T) -> Self {
1065		Self(t)
1066	}
1067}
1068
1069impl<T: MaxEncodedLen> MaxEncodedLen for WrapperOpaque<T> {
1070	fn max_encoded_len() -> usize {
1071		let t_max_len = T::max_encoded_len();
1072
1073		// See scale encoding: https://docs.substrate.io/reference/scale-codec/
1074		if t_max_len < 64 {
1075			t_max_len + 1
1076		} else if t_max_len < 2usize.pow(14) {
1077			t_max_len + 2
1078		} else if t_max_len < 2usize.pow(30) {
1079			t_max_len + 4
1080		} else {
1081			<codec::Compact<u32>>::max_encoded_len().saturating_add(T::max_encoded_len())
1082		}
1083	}
1084}
1085
1086impl<T: TypeInfo + 'static> TypeInfo for WrapperOpaque<T> {
1087	type Identity = Self;
1088	fn type_info() -> Type {
1089		Type::builder()
1090			.path(Path::new("WrapperOpaque", module_path!()))
1091			.type_params(vec![TypeParameter::new("T", Some(meta_type::<T>()))])
1092			.composite(
1093				Fields::unnamed()
1094					.field(|f| f.compact::<u32>())
1095					.field(|f| f.ty::<T>().type_name("T")),
1096			)
1097	}
1098}
1099
1100/// A wrapper for any type `T` which implement encode/decode in a way compatible with `Vec<u8>`.
1101///
1102/// This type is similar to [`WrapperOpaque`], but it differs in the way it stores the type `T`.
1103/// While [`WrapperOpaque`] stores the decoded type, the [`WrapperKeepOpaque`] stores the type only
1104/// in its opaque format, aka as a `Vec<u8>`. To access the real type `T` [`Self::try_decode`] needs
1105/// to be used.
1106#[derive(Debug, Eq, PartialEq, Default, Clone)]
1107pub struct WrapperKeepOpaque<T> {
1108	data: Vec<u8>,
1109	_phantom: core::marker::PhantomData<T>,
1110}
1111
1112impl<T: Decode> WrapperKeepOpaque<T> {
1113	/// Try to decode the wrapped type from the inner `data`.
1114	///
1115	/// Returns `None` if the decoding failed.
1116	pub fn try_decode(&self) -> Option<T> {
1117		T::decode_all_with_depth_limit(crate::MAX_EXTRINSIC_DEPTH, &mut &self.data[..]).ok()
1118	}
1119
1120	/// Returns the length of the encoded `T`.
1121	pub fn encoded_len(&self) -> usize {
1122		self.data.len()
1123	}
1124
1125	/// Returns the encoded data.
1126	pub fn encoded(&self) -> &[u8] {
1127		&self.data
1128	}
1129
1130	/// Create from the given encoded `data`.
1131	pub fn from_encoded(data: Vec<u8>) -> Self {
1132		Self { data, _phantom: core::marker::PhantomData }
1133	}
1134}
1135
1136impl<T: Encode> EncodeLike for WrapperKeepOpaque<T> {}
1137impl<T: Encode> EncodeLike<WrapperOpaque<T>> for WrapperKeepOpaque<T> {}
1138
1139impl<T: Encode> Encode for WrapperKeepOpaque<T> {
1140	fn size_hint(&self) -> usize {
1141		self.data.len() + codec::Compact::<u32>::compact_len(&(self.data.len() as u32))
1142	}
1143
1144	fn encode_to<O: codec::Output + ?Sized>(&self, dest: &mut O) {
1145		self.data.encode_to(dest);
1146	}
1147
1148	fn encode(&self) -> Vec<u8> {
1149		self.data.encode()
1150	}
1151
1152	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
1153		self.data.using_encoded(f)
1154	}
1155}
1156
1157impl<T: Decode> Decode for WrapperKeepOpaque<T> {
1158	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
1159		Ok(Self { data: Vec::<u8>::decode(input)?, _phantom: core::marker::PhantomData })
1160	}
1161
1162	fn skip<I: Input>(input: &mut I) -> Result<(), codec::Error> {
1163		<Vec<u8>>::skip(input)
1164	}
1165}
1166
1167impl<T: MaxEncodedLen> MaxEncodedLen for WrapperKeepOpaque<T> {
1168	fn max_encoded_len() -> usize {
1169		WrapperOpaque::<T>::max_encoded_len()
1170	}
1171}
1172
1173impl<T: TypeInfo + 'static> TypeInfo for WrapperKeepOpaque<T> {
1174	type Identity = Self;
1175	fn type_info() -> Type {
1176		Type::builder()
1177			.path(Path::new("WrapperKeepOpaque", module_path!()))
1178			.type_params(vec![TypeParameter::new("T", Some(meta_type::<T>()))])
1179			.composite(
1180				Fields::unnamed()
1181					.field(|f| f.compact::<u32>())
1182					.field(|f| f.ty::<T>().type_name("T")),
1183			)
1184	}
1185}
1186
1187/// A interface for looking up preimages from their hash on chain.
1188pub trait PreimageProvider<Hash> {
1189	/// Returns whether a preimage exists for a given hash.
1190	///
1191	/// A value of `true` implies that `get_preimage` is `Some`.
1192	fn have_preimage(hash: &Hash) -> bool;
1193
1194	/// Returns the preimage for a given hash.
1195	fn get_preimage(hash: &Hash) -> Option<Vec<u8>>;
1196
1197	/// Returns whether a preimage request exists for a given hash.
1198	fn preimage_requested(hash: &Hash) -> bool;
1199
1200	/// Request that someone report a preimage. Providers use this to optimise the economics for
1201	/// preimage reporting.
1202	fn request_preimage(hash: &Hash);
1203
1204	/// Cancel a previous preimage request.
1205	fn unrequest_preimage(hash: &Hash);
1206}
1207
1208impl<Hash> PreimageProvider<Hash> for () {
1209	fn have_preimage(_: &Hash) -> bool {
1210		false
1211	}
1212	fn get_preimage(_: &Hash) -> Option<Vec<u8>> {
1213		None
1214	}
1215	fn preimage_requested(_: &Hash) -> bool {
1216		false
1217	}
1218	fn request_preimage(_: &Hash) {}
1219	fn unrequest_preimage(_: &Hash) {}
1220}
1221
1222/// A interface for managing preimages to hashes on chain.
1223///
1224/// Note that this API does not assume any underlying user is calling, and thus
1225/// does not handle any preimage ownership or fees. Other system level logic that
1226/// uses this API should implement that on their own side.
1227pub trait PreimageRecipient<Hash>: PreimageProvider<Hash> {
1228	/// Maximum size of a preimage.
1229	type MaxSize: Get<u32>;
1230
1231	/// Store the bytes of a preimage on chain infallible due to the bounded type.
1232	fn note_preimage(bytes: crate::BoundedVec<u8, Self::MaxSize>);
1233
1234	/// Clear a previously noted preimage. This is infallible and should be treated more like a
1235	/// hint - if it was not previously noted or if it is now requested, then this will not do
1236	/// anything.
1237	fn unnote_preimage(hash: &Hash);
1238}
1239
1240impl<Hash> PreimageRecipient<Hash> for () {
1241	type MaxSize = ();
1242	fn note_preimage(_: crate::BoundedVec<u8, Self::MaxSize>) {}
1243	fn unnote_preimage(_: &Hash) {}
1244}
1245
1246/// Trait for touching/creating an asset account with a deposit taken from a designated depositor
1247/// specified by the client.
1248///
1249/// Ensures that transfers to the touched account will succeed without being denied by the account
1250/// creation requirements. For example, it is useful for the account creation of non-sufficient
1251/// assets when its system account may not have the free consumer reference required for it. If
1252/// there is no risk of failing to meet those requirements, the touch operation can be a no-op, as
1253/// is common for native assets.
1254pub trait AccountTouch<AssetId, AccountId> {
1255	/// The type for currency units of the deposit.
1256	type Balance;
1257
1258	/// The deposit amount of a native currency required for touching an account of the `asset`.
1259	fn deposit_required(asset: AssetId) -> Self::Balance;
1260
1261	/// Check if an account for a given asset should be touched to meet the existence requirements.
1262	fn should_touch(asset: AssetId, who: &AccountId) -> bool;
1263
1264	/// Create an account for `who` of the `asset` with a deposit taken from the `depositor`.
1265	fn touch(asset: AssetId, who: &AccountId, depositor: &AccountId) -> DispatchResult;
1266}
1267
1268/// Trait for reporting additional validator reward points
1269pub trait RewardsReporter<ValidatorId> {
1270	/// The input is an iterator of tuples of validator account IDs and the amount of points they
1271	/// should be rewarded.
1272	fn reward_by_ids(validators_points: impl IntoIterator<Item = (ValidatorId, u32)>);
1273}
1274
1275#[cfg(test)]
1276mod test {
1277	use super::*;
1278	use core::marker::PhantomData;
1279	use subsoil::core::bounded::{BoundedSlice, BoundedVec};
1280
1281	#[test]
1282	fn defensive_assert_works() {
1283		defensive_assert!(true);
1284		defensive_assert!(true,);
1285		defensive_assert!(true, "must work");
1286		defensive_assert!(true, "must work",);
1287	}
1288
1289	#[test]
1290	#[cfg(debug_assertions)]
1291	#[should_panic(expected = "Defensive failure has been triggered!: \"1 == 0\": \"Must fail\"")]
1292	fn defensive_assert_panics() {
1293		defensive_assert!(1 == 0, "Must fail");
1294	}
1295
1296	#[test]
1297	#[cfg(not(debug_assertions))]
1298	fn defensive_assert_does_not_panic() {
1299		defensive_assert!(1 == 0, "Must fail");
1300	}
1301
1302	#[test]
1303	#[cfg(not(debug_assertions))]
1304	fn defensive_saturating_accrue_works() {
1305		let mut v = 1_u32;
1306		v.defensive_saturating_accrue(2);
1307		assert_eq!(v, 3);
1308		v.defensive_saturating_accrue(u32::MAX);
1309		assert_eq!(v, u32::MAX);
1310		v.defensive_saturating_accrue(1);
1311		assert_eq!(v, u32::MAX);
1312	}
1313
1314	#[test]
1315	#[cfg(debug_assertions)]
1316	#[should_panic(expected = "Defensive")]
1317	fn defensive_saturating_accrue_panics() {
1318		let mut v = u32::MAX;
1319		v.defensive_saturating_accrue(1); // defensive failure
1320	}
1321
1322	#[test]
1323	#[cfg(not(debug_assertions))]
1324	fn defensive_saturating_reduce_works() {
1325		let mut v = u32::MAX;
1326		v.defensive_saturating_reduce(3);
1327		assert_eq!(v, u32::MAX - 3);
1328		v.defensive_saturating_reduce(u32::MAX);
1329		assert_eq!(v, 0);
1330		v.defensive_saturating_reduce(1);
1331		assert_eq!(v, 0);
1332	}
1333
1334	#[test]
1335	#[cfg(debug_assertions)]
1336	#[should_panic(expected = "Defensive")]
1337	fn defensive_saturating_reduce_panics() {
1338		let mut v = 0_u32;
1339		v.defensive_saturating_reduce(1); // defensive failure
1340	}
1341
1342	#[test]
1343	#[cfg(not(debug_assertions))]
1344	fn defensive_saturating_inc_works() {
1345		let mut v = 0_u32;
1346		for i in 1..10 {
1347			v.defensive_saturating_inc();
1348			assert_eq!(v, i);
1349		}
1350		v += u32::MAX - 10;
1351		v.defensive_saturating_inc();
1352		assert_eq!(v, u32::MAX);
1353		v.defensive_saturating_inc();
1354		assert_eq!(v, u32::MAX);
1355	}
1356
1357	#[test]
1358	#[cfg(debug_assertions)]
1359	#[should_panic(expected = "Defensive")]
1360	fn defensive_saturating_inc_panics() {
1361		let mut v = u32::MAX;
1362		v.defensive_saturating_inc(); // defensive failure
1363	}
1364
1365	#[test]
1366	#[cfg(not(debug_assertions))]
1367	fn defensive_saturating_dec_works() {
1368		let mut v = u32::MAX;
1369		for i in 1..10 {
1370			v.defensive_saturating_dec();
1371			assert_eq!(v, u32::MAX - i);
1372		}
1373		v -= u32::MAX - 10;
1374		v.defensive_saturating_dec();
1375		assert_eq!(v, 0);
1376		v.defensive_saturating_dec();
1377		assert_eq!(v, 0);
1378	}
1379
1380	#[test]
1381	#[cfg(debug_assertions)]
1382	#[should_panic(expected = "Defensive")]
1383	fn defensive_saturating_dec_panics() {
1384		let mut v = 0_u32;
1385		v.defensive_saturating_dec(); // defensive failure
1386	}
1387
1388	#[test]
1389	#[cfg(not(debug_assertions))]
1390	fn defensive_truncating_from_vec_defensive_works() {
1391		let unbound = vec![1u32, 2];
1392		let bound = BoundedVec::<u32, ConstU32<1>>::defensive_truncate_from(unbound);
1393		assert_eq!(bound, vec![1u32]);
1394	}
1395
1396	#[test]
1397	#[cfg(not(debug_assertions))]
1398	fn defensive_truncating_from_slice_defensive_works() {
1399		let unbound = &[1u32, 2];
1400		let bound = BoundedSlice::<u32, ConstU32<1>>::defensive_truncate_from(unbound);
1401		assert_eq!(bound, &[1u32][..]);
1402	}
1403
1404	#[test]
1405	#[cfg(debug_assertions)]
1406	#[should_panic(
1407		expected = "Defensive failure has been triggered!: \"DefensiveTruncateFrom truncating\""
1408	)]
1409	fn defensive_truncating_from_vec_defensive_panics() {
1410		let unbound = vec![1u32, 2];
1411		let _ = BoundedVec::<u32, ConstU32<1>>::defensive_truncate_from(unbound);
1412	}
1413
1414	#[test]
1415	#[cfg(debug_assertions)]
1416	#[should_panic(
1417		expected = "Defensive failure has been triggered!: \"DefensiveTruncateFrom truncating\""
1418	)]
1419	fn defensive_truncating_from_slice_defensive_panics() {
1420		let unbound = &[1u32, 2];
1421		let _ = BoundedSlice::<u32, ConstU32<1>>::defensive_truncate_from(unbound);
1422	}
1423
1424	#[test]
1425	fn defensive_truncate_from_vec_works() {
1426		let unbound = vec![1u32, 2, 3];
1427		let bound = BoundedVec::<u32, ConstU32<3>>::defensive_truncate_from(unbound.clone());
1428		assert_eq!(bound, unbound);
1429	}
1430
1431	#[test]
1432	fn defensive_truncate_from_slice_works() {
1433		let unbound = [1u32, 2, 3];
1434		let bound = BoundedSlice::<u32, ConstU32<3>>::defensive_truncate_from(&unbound);
1435		assert_eq!(bound, &unbound[..]);
1436	}
1437
1438	#[derive(Encode, Decode)]
1439	enum NestedType {
1440		Nested(Box<Self>),
1441		Done,
1442	}
1443
1444	#[test]
1445	fn test_opaque_wrapper_decode_limit() {
1446		let limit = crate::MAX_EXTRINSIC_DEPTH as usize;
1447		let mut ok_bytes = vec![0u8; limit];
1448		ok_bytes.push(1u8);
1449		let mut err_bytes = vec![0u8; limit + 1];
1450		err_bytes.push(1u8);
1451		assert!(<WrapperOpaque<NestedType>>::decode(&mut &ok_bytes.encode()[..]).is_ok());
1452		assert!(<WrapperOpaque<NestedType>>::decode(&mut &err_bytes.encode()[..]).is_err());
1453
1454		let ok_keep_opaque = WrapperKeepOpaque { data: ok_bytes, _phantom: PhantomData };
1455		let err_keep_opaque = WrapperKeepOpaque { data: err_bytes, _phantom: PhantomData };
1456
1457		assert!(<WrapperKeepOpaque<NestedType>>::try_decode(&ok_keep_opaque).is_some());
1458		assert!(<WrapperKeepOpaque<NestedType>>::try_decode(&err_keep_opaque).is_none());
1459	}
1460
1461	#[test]
1462	fn test_opaque_wrapper() {
1463		let encoded = WrapperOpaque(3u32).encode();
1464		assert_eq!(encoded, [codec::Compact(4u32).encode(), 3u32.to_le_bytes().to_vec()].concat());
1465		let vec_u8 = <Vec<u8>>::decode(&mut &encoded[..]).unwrap();
1466		let decoded_from_vec_u8 = u32::decode(&mut &vec_u8[..]).unwrap();
1467		assert_eq!(decoded_from_vec_u8, 3u32);
1468		let decoded = <WrapperOpaque<u32>>::decode(&mut &encoded[..]).unwrap();
1469		assert_eq!(decoded.0, 3u32);
1470
1471		assert_eq!(<WrapperOpaque<[u8; 63]>>::max_encoded_len(), 63 + 1);
1472		assert_eq!(
1473			<WrapperOpaque<[u8; 63]>>::max_encoded_len(),
1474			WrapperOpaque([0u8; 63]).encode().len()
1475		);
1476
1477		assert_eq!(<WrapperOpaque<[u8; 64]>>::max_encoded_len(), 64 + 2);
1478		assert_eq!(
1479			<WrapperOpaque<[u8; 64]>>::max_encoded_len(),
1480			WrapperOpaque([0u8; 64]).encode().len()
1481		);
1482
1483		assert_eq!(
1484			<WrapperOpaque<[u8; 2usize.pow(14) - 1]>>::max_encoded_len(),
1485			2usize.pow(14) - 1 + 2
1486		);
1487		assert_eq!(<WrapperOpaque<[u8; 2usize.pow(14)]>>::max_encoded_len(), 2usize.pow(14) + 4);
1488
1489		let data = 4u64;
1490		// Ensure that we check that the `Vec<u8>` is consumed completely on decode.
1491		assert!(WrapperOpaque::<u32>::decode(&mut &data.encode().encode()[..]).is_err());
1492	}
1493
1494	#[test]
1495	fn test_keep_opaque_wrapper() {
1496		let data = 3u32.encode().encode();
1497
1498		let keep_opaque = WrapperKeepOpaque::<u32>::decode(&mut &data[..]).unwrap();
1499		keep_opaque.try_decode().unwrap();
1500
1501		let data = WrapperOpaque(50u32).encode();
1502		let decoded = WrapperKeepOpaque::<u32>::decode(&mut &data[..]).unwrap();
1503		let data = decoded.encode();
1504		WrapperOpaque::<u32>::decode(&mut &data[..]).unwrap();
1505	}
1506
1507	#[test]
1508	fn defensive_min_works() {
1509		assert_eq!(10, 10_u32.defensive_min(11_u32));
1510		assert_eq!(10, 10_u32.defensive_min(10_u32));
1511	}
1512
1513	#[test]
1514	#[cfg(debug_assertions)]
1515	#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMin\"")]
1516	fn defensive_min_panics() {
1517		10_u32.defensive_min(9_u32);
1518	}
1519
1520	#[test]
1521	fn defensive_strict_min_works() {
1522		assert_eq!(10, 10_u32.defensive_strict_min(11_u32));
1523		assert_eq!(9, 9_u32.defensive_strict_min(10_u32));
1524	}
1525
1526	#[test]
1527	#[cfg(debug_assertions)]
1528	#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMin strict\"")]
1529	fn defensive_strict_min_panics() {
1530		9_u32.defensive_strict_min(9_u32);
1531	}
1532
1533	#[test]
1534	fn defensive_max_works() {
1535		assert_eq!(11, 11_u32.defensive_max(10_u32));
1536		assert_eq!(10, 10_u32.defensive_max(10_u32));
1537	}
1538
1539	#[test]
1540	#[cfg(debug_assertions)]
1541	#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMax\"")]
1542	fn defensive_max_panics() {
1543		9_u32.defensive_max(10_u32);
1544	}
1545
1546	#[test]
1547	fn defensive_strict_max_works() {
1548		assert_eq!(11, 11_u32.defensive_strict_max(10_u32));
1549		assert_eq!(10, 10_u32.defensive_strict_max(9_u32));
1550	}
1551
1552	#[test]
1553	#[cfg(debug_assertions)]
1554	#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMax strict\"")]
1555	fn defensive_strict_max_panics() {
1556		9_u32.defensive_strict_max(9_u32);
1557	}
1558}