1use 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
33pub trait VariantCount {
35 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
47pub 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#[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#[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
108pub mod defensive_prelude {
110 pub use super::{Defensive, DefensiveOption, DefensiveResult};
111}
112
113pub trait Defensive<T> {
131 fn defensive_unwrap_or(self, other: T) -> T;
134
135 fn defensive_unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T;
138
139 fn defensive_unwrap_or_default(self) -> T
142 where
143 T: Default;
144
145 fn defensive(self) -> Self;
157
158 fn defensive_proof(self, proof: &'static str) -> Self;
161}
162
163pub trait DefensiveResult<T, E> {
165 fn defensive_map_err<F, O: FnOnce(E) -> F>(self, o: O) -> Result<T, F>;
168
169 fn defensive_map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U;
172
173 fn defensive_ok(self) -> Option<T>;
176
177 fn defensive_map<U, F: FnOnce(T) -> U>(self, f: F) -> Result<U, E>;
180}
181
182pub trait DefensiveOption<T> {
184 fn defensive_map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U;
187
188 fn defensive_ok_or_else<E: core::fmt::Debug, F: FnOnce() -> E>(self, err: F) -> Result<T, E>;
191
192 fn defensive_ok_or<E: core::fmt::Debug>(self, err: E) -> Result<T, E>;
194
195 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
383pub trait DefensiveSaturating {
386 fn defensive_saturating_add(self, other: Self) -> Self;
388 fn defensive_saturating_sub(self, other: Self) -> Self;
390 fn defensive_saturating_mul(self, other: Self) -> Self;
392 fn defensive_saturating_accrue(&mut self, other: Self);
394 fn defensive_saturating_reduce(&mut self, other: Self);
396 fn defensive_saturating_inc(&mut self);
398 fn defensive_saturating_dec(&mut self);
400}
401
402impl<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 *self = core::mem::replace(self, One::one()).defensive_saturating_add(other);
417 }
418 fn defensive_saturating_reduce(&mut self, other: Self) {
419 *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
430pub trait DefensiveTruncateFrom<T> {
432 fn defensive_truncate_from(unbound: T) -> Self;
446}
447
448impl<T, U> DefensiveTruncateFrom<U> for T
449where
450 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
467pub trait DefensiveTruncateInto<T> {
469 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}
478pub trait DefensiveMin<T> {
482 fn defensive_min(self, other: T) -> Self;
500
501 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
542pub trait DefensiveMax<T> {
546 fn defensive_max(self, other: T) -> Self;
564
565 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
606pub trait Len {
608 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
621pub trait TryDrop: Sized {
623 fn try_drop(self) -> Result<(), Self>;
625}
626
627impl TryDrop for () {
628 fn try_drop(self) -> Result<(), Self> {
629 Ok(())
630 }
631}
632
633pub enum SameOrOther<A, B> {
637 None,
639 Same(A),
641 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 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 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 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#[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 fn on_new_account(who: &AccountId);
712}
713
714#[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 fn on_killed_account(who: &AccountId);
721}
722
723pub trait HandleLifetime<T> {
725 fn created(_t: &T) -> Result<(), DispatchError> {
727 Ok(())
728 }
729
730 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
748pub trait UnixTime {
750 fn now() -> core::time::Duration;
752}
753
754pub trait IsType<T>: Into<T> + From<T> {
758 fn from_ref(t: &T) -> &Self;
760
761 fn into_ref(&self) -> &T;
763
764 fn from_mut(t: &mut T) -> &mut Self;
766
767 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
786pub trait IsSubType<T> {
829 fn is_sub_type(&self) -> Option<&T>;
831}
832
833pub trait ExecuteBlock<Block: BlockT> {
838 fn execute_block(mut block: Block::LazyBlock) {
851 Self::verify_and_remove_seal(&mut block);
852 Self::execute_verified_block(block);
853 }
854
855 fn verify_and_remove_seal(block: &mut Block::LazyBlock);
864
865 fn execute_verified_block(block: Block::LazyBlock);
871}
872
873pub trait PrivilegeCmp<Origin> {
875 fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering>;
881}
882
883pub 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#[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 fn offchain_worker(_n: BlockNumber) {}
914}
915
916pub struct Backing {
919 pub approvals: u32,
921 pub eligible: u32,
923}
924
925pub trait GetBacking {
927 fn get_backing(&self) -> Option<Backing>;
930}
931
932pub trait IsInherent<Extrinsic> {
934 fn is_inherent(ext: &Extrinsic) -> bool;
936}
937
938pub trait InherentBuilder: ExtrinsicCall {
940 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
957pub trait SignedTransactionBuilder: ExtrinsicCall {
959 type Address;
960 type Signature;
961 type Extension;
962
963 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
995pub trait EstimateCallFee<Call, Balance> {
999 fn estimate_call_fee(call: &Call, post_info: crate::dispatch::PostDispatchInfo) -> Balance;
1004}
1005
1006#[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#[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 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#[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 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 pub fn encoded_len(&self) -> usize {
1122 self.data.len()
1123 }
1124
1125 pub fn encoded(&self) -> &[u8] {
1127 &self.data
1128 }
1129
1130 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
1187pub trait PreimageProvider<Hash> {
1189 fn have_preimage(hash: &Hash) -> bool;
1193
1194 fn get_preimage(hash: &Hash) -> Option<Vec<u8>>;
1196
1197 fn preimage_requested(hash: &Hash) -> bool;
1199
1200 fn request_preimage(hash: &Hash);
1203
1204 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
1222pub trait PreimageRecipient<Hash>: PreimageProvider<Hash> {
1228 type MaxSize: Get<u32>;
1230
1231 fn note_preimage(bytes: crate::BoundedVec<u8, Self::MaxSize>);
1233
1234 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
1246pub trait AccountTouch<AssetId, AccountId> {
1255 type Balance;
1257
1258 fn deposit_required(asset: AssetId) -> Self::Balance;
1260
1261 fn should_touch(asset: AssetId, who: &AccountId) -> bool;
1263
1264 fn touch(asset: AssetId, who: &AccountId, depositor: &AccountId) -> DispatchResult;
1266}
1267
1268pub trait RewardsReporter<ValidatorId> {
1270 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); }
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); }
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(); }
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(); }
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 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}