1use crate::{
21 generic::Digest,
22 scale_info::{StaticTypeInfo, TypeInfo},
23 transaction_validity::{
24 TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
25 ValidTransaction,
26 },
27 DispatchResult, KeyTypeId, OpaqueExtrinsic,
28};
29use alloc::vec::Vec;
30use codec::{
31 Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, FullCodec, HasCompact, MaxEncodedLen,
32};
33#[doc(hidden)]
34pub use core::{fmt::Debug, marker::PhantomData};
35use impl_trait_for_tuples::impl_for_tuples;
36#[cfg(feature = "serde")]
37use serde::{de::DeserializeOwned, Deserialize, Serialize};
38use sp_application_crypto::AppCrypto;
39pub use sp_arithmetic::traits::{
40 checked_pow, ensure_pow, AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedDiv,
41 CheckedMul, CheckedShl, CheckedShr, CheckedSub, Ensure, EnsureAdd, EnsureAddAssign, EnsureDiv,
42 EnsureDivAssign, EnsureFixedPointNumber, EnsureFrom, EnsureInto, EnsureMul, EnsureMulAssign,
43 EnsureOp, EnsureOpAssign, EnsureSub, EnsureSubAssign, IntegerSquareRoot, One,
44 SaturatedConversion, Saturating, UniqueSaturatedFrom, UniqueSaturatedInto, Zero,
45};
46use sp_core::{self, storage::StateVersion, Hasher, TypeId, U256};
47#[doc(hidden)]
48pub use sp_core::{
49 parameter_types, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstInt,
50 ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, ConstUint, Get, GetDefault, TryCollect,
51 TypedGet,
52};
53#[cfg(feature = "std")]
54use std::fmt::Display;
55#[cfg(feature = "std")]
56use std::str::FromStr;
57
58pub mod transaction_extension;
59pub use transaction_extension::{
60 DispatchTransaction, Implication, ImplicationParts, TransactionExtension,
61 TransactionExtensionMetadata, TxBaseImplication, ValidateResult,
62};
63
64pub trait Lazy<T: ?Sized> {
66 fn get(&mut self) -> &T;
70}
71
72impl<'a> Lazy<[u8]> for &'a [u8] {
73 fn get(&mut self) -> &[u8] {
74 self
75 }
76}
77
78pub trait IdentifyAccount {
81 type AccountId;
83 fn into_account(self) -> Self::AccountId;
85}
86
87impl IdentifyAccount for sp_core::ed25519::Public {
88 type AccountId = Self;
89 fn into_account(self) -> Self {
90 self
91 }
92}
93
94impl IdentifyAccount for sp_core::sr25519::Public {
95 type AccountId = Self;
96 fn into_account(self) -> Self {
97 self
98 }
99}
100
101impl IdentifyAccount for sp_core::ecdsa::Public {
102 type AccountId = Self;
103 fn into_account(self) -> Self {
104 self
105 }
106}
107
108#[cfg(feature = "bls-experimental")]
109impl IdentifyAccount for sp_core::ecdsa_bls381::Public {
110 type AccountId = Self;
111 fn into_account(self) -> Self {
112 self
113 }
114}
115
116pub trait Verify {
118 type Signer: IdentifyAccount;
120 fn verify<L: Lazy<[u8]>>(
124 &self,
125 msg: L,
126 signer: &<Self::Signer as IdentifyAccount>::AccountId,
127 ) -> bool;
128}
129
130impl Verify for sp_core::ed25519::Signature {
131 type Signer = sp_core::ed25519::Public;
132
133 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ed25519::Public) -> bool {
134 sp_io::crypto::ed25519_verify(self, msg.get(), signer)
135 }
136}
137
138impl Verify for sp_core::sr25519::Signature {
139 type Signer = sp_core::sr25519::Public;
140
141 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::sr25519::Public) -> bool {
142 sp_io::crypto::sr25519_verify(self, msg.get(), signer)
143 }
144}
145
146impl Verify for sp_core::ecdsa::Signature {
147 type Signer = sp_core::ecdsa::Public;
148 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa::Public) -> bool {
149 match sp_io::crypto::secp256k1_ecdsa_recover_compressed(
150 self.as_ref(),
151 &sp_io::hashing::blake2_256(msg.get()),
152 ) {
153 Ok(pubkey) => signer.0 == pubkey,
154 _ => false,
155 }
156 }
157}
158
159#[cfg(feature = "bls-experimental")]
160impl Verify for sp_core::ecdsa_bls381::Signature {
161 type Signer = sp_core::ecdsa_bls381::Public;
162 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa_bls381::Public) -> bool {
163 <sp_core::ecdsa_bls381::Pair as sp_core::Pair>::verify(self, msg.get(), signer)
164 }
165}
166
167pub trait AppVerify {
169 type AccountId;
171 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &Self::AccountId) -> bool;
173}
174
175impl<
176 S: Verify<Signer = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic>
177 + From<T>,
178 T: sp_application_crypto::Wraps<Inner = S>
179 + sp_application_crypto::AppCrypto
180 + sp_application_crypto::AppSignature
181 + AsRef<S>
182 + AsMut<S>
183 + From<S>,
184 > AppVerify for T
185where
186 <S as Verify>::Signer: IdentifyAccount<AccountId = <S as Verify>::Signer>,
187 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
188 AccountId = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic,
189 >,
190{
191 type AccountId = <T as AppCrypto>::Public;
192 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppCrypto>::Public) -> bool {
193 use sp_application_crypto::IsWrappedBy;
194 let inner: &S = self.as_ref();
195 let inner_pubkey =
196 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(
197 signer,
198 );
199 Verify::verify(inner, msg, inner_pubkey)
200 }
201}
202
203#[derive(Encode, Decode, Debug)]
205pub struct BadOrigin;
206
207impl From<BadOrigin> for &'static str {
208 fn from(_: BadOrigin) -> &'static str {
209 "Bad origin"
210 }
211}
212
213#[derive(Encode, Decode, Debug)]
215pub struct LookupError;
216
217impl From<LookupError> for &'static str {
218 fn from(_: LookupError) -> &'static str {
219 "Can not lookup"
220 }
221}
222
223impl From<LookupError> for TransactionValidityError {
224 fn from(_: LookupError) -> Self {
225 UnknownTransaction::CannotLookup.into()
226 }
227}
228
229pub trait Lookup {
231 type Source;
233 type Target;
235 fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError>;
237}
238
239pub trait StaticLookup {
243 type Source: Codec + Clone + PartialEq + Debug + TypeInfo;
245 type Target;
247 fn lookup(s: Self::Source) -> Result<Self::Target, LookupError>;
249 fn unlookup(t: Self::Target) -> Self::Source;
251}
252
253#[derive(Clone, Copy, PartialEq, Eq)]
255pub struct IdentityLookup<T>(PhantomData<T>);
256impl<T> Default for IdentityLookup<T> {
257 fn default() -> Self {
258 Self(PhantomData::<T>::default())
259 }
260}
261
262impl<T: Codec + Clone + PartialEq + Debug + TypeInfo> StaticLookup for IdentityLookup<T> {
263 type Source = T;
264 type Target = T;
265 fn lookup(x: T) -> Result<T, LookupError> {
266 Ok(x)
267 }
268 fn unlookup(x: T) -> T {
269 x
270 }
271}
272
273impl<T> Lookup for IdentityLookup<T> {
274 type Source = T;
275 type Target = T;
276 fn lookup(&self, x: T) -> Result<T, LookupError> {
277 Ok(x)
278 }
279}
280
281pub struct AccountIdLookup<AccountId, AccountIndex>(PhantomData<(AccountId, AccountIndex)>);
283impl<AccountId, AccountIndex> StaticLookup for AccountIdLookup<AccountId, AccountIndex>
284where
285 AccountId: Codec + Clone + PartialEq + Debug,
286 AccountIndex: Codec + Clone + PartialEq + Debug,
287 crate::MultiAddress<AccountId, AccountIndex>: Codec + StaticTypeInfo,
288{
289 type Source = crate::MultiAddress<AccountId, AccountIndex>;
290 type Target = AccountId;
291 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
292 match x {
293 crate::MultiAddress::Id(i) => Ok(i),
294 _ => Err(LookupError),
295 }
296 }
297 fn unlookup(x: Self::Target) -> Self::Source {
298 crate::MultiAddress::Id(x)
299 }
300}
301
302impl<A, B> StaticLookup for (A, B)
304where
305 A: StaticLookup,
306 B: StaticLookup<Source = A::Source, Target = A::Target>,
307{
308 type Source = A::Source;
309 type Target = A::Target;
310
311 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
312 A::lookup(x.clone()).or_else(|_| B::lookup(x))
313 }
314 fn unlookup(x: Self::Target) -> Self::Source {
315 A::unlookup(x)
316 }
317}
318
319pub trait Morph<A> {
322 type Outcome;
324
325 fn morph(a: A) -> Self::Outcome;
327}
328
329impl<T> Morph<T> for Identity {
331 type Outcome = T;
332 fn morph(a: T) -> T {
333 a
334 }
335}
336
337pub trait TryMorph<A> {
340 type Outcome;
342
343 fn try_morph(a: A) -> Result<Self::Outcome, ()>;
345}
346
347impl<T> TryMorph<T> for Identity {
349 type Outcome = T;
350 fn try_morph(a: T) -> Result<T, ()> {
351 Ok(a)
352 }
353}
354
355pub struct MorphInto<T>(core::marker::PhantomData<T>);
357impl<T, A: Into<T>> Morph<A> for MorphInto<T> {
358 type Outcome = T;
359 fn morph(a: A) -> T {
360 a.into()
361 }
362}
363
364pub struct TryMorphInto<T>(core::marker::PhantomData<T>);
366impl<T, A: TryInto<T>> TryMorph<A> for TryMorphInto<T> {
367 type Outcome = T;
368 fn try_morph(a: A) -> Result<T, ()> {
369 a.try_into().map_err(|_| ())
370 }
371}
372
373pub struct TakeFirst;
375impl<T1> Morph<(T1,)> for TakeFirst {
376 type Outcome = T1;
377 fn morph(a: (T1,)) -> T1 {
378 a.0
379 }
380}
381impl<T1, T2> Morph<(T1, T2)> for TakeFirst {
382 type Outcome = T1;
383 fn morph(a: (T1, T2)) -> T1 {
384 a.0
385 }
386}
387impl<T1, T2, T3> Morph<(T1, T2, T3)> for TakeFirst {
388 type Outcome = T1;
389 fn morph(a: (T1, T2, T3)) -> T1 {
390 a.0
391 }
392}
393impl<T1, T2, T3, T4> Morph<(T1, T2, T3, T4)> for TakeFirst {
394 type Outcome = T1;
395 fn morph(a: (T1, T2, T3, T4)) -> T1 {
396 a.0
397 }
398}
399
400#[macro_export]
436macro_rules! morph_types {
437 (
438 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ()
439 ) => {
440 $( #[doc = $doc] )* $vq struct $name;
441 };
442 (
443 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ( $( $bound_id:ident ),+ )
444 ) => {
445 $( #[doc = $doc] )*
446 $vq struct $name < $($bound_id,)* > ( $crate::traits::PhantomData< ( $($bound_id,)* ) > ) ;
447 };
448 (
449 @IMPL $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
450 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
451 ) => {
452 impl<$($bounds)*> $crate::traits::Morph<$var_type> for $name $( $where )? {
453 type Outcome = $outcome;
454 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
455 }
456 };
457 (
458 @IMPL_TRY $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
459 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
460 ) => {
461 impl<$($bounds)*> $crate::traits::TryMorph<$var_type> for $name $( $where )? {
462 type Outcome = $outcome;
463 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
464 }
465 };
466 (
467 @IMPL $name:ty : () ( $( $where:tt )* )
468 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
469 ) => {
470 impl $crate::traits::Morph<$var_type> for $name $( $where )? {
471 type Outcome = $outcome;
472 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
473 }
474 };
475 (
476 @IMPL_TRY $name:ty : () ( $( $where:tt )* )
477 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
478 ) => {
479 impl $crate::traits::TryMorph<$var_type> for $name $( $where )? {
480 type Outcome = $outcome;
481 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
482 }
483 };
484 (
485 @IMPL_BOTH $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
486 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
487 ) => {
488 morph_types! {
489 @IMPL $name : ($($bounds)*) ($($where)*)
490 = |$var: $var_type| -> $outcome { $( $ex )* }
491 }
492 morph_types! {
493 @IMPL_TRY $name : ($($bounds)*) ($($where)*)
494 = |$var: $var_type| -> $outcome { Ok({$( $ex )*}) }
495 }
496 };
497
498 (
499 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
500 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
501 $(: $type:tt)?
502 = |_| -> $outcome:ty { $( $ex:expr )* };
503 $( $rest:tt )*
504 ) => {
505 morph_types! {
506 $( #[doc = $doc] )* $vq type $name
507 $( < $( $bound_id $( : $bound_head $( | $bound_tail )* )? ),+ > )?
508 EXTRA_GENERIC(X)
509 $(: $type)?
510 = |_x: X| -> $outcome { $( $ex )* };
511 $( $rest )*
512 }
513 };
514 (
515 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
516 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
517 $( EXTRA_GENERIC ($extra:ident) )?
518 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
519 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
520 $( $rest:tt )*
521 ) => {
522 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
523 morph_types! {
524 @IMPL_BOTH $name $( < $( $bound_id ),* > )? :
525 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
526 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
527 = |$var: $var_type| -> $outcome { $( $ex )* }
528 }
529 morph_types!{ $($rest)* }
530 };
531 (
532 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
533 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
534 $( EXTRA_GENERIC ($extra:ident) )?
535 : Morph
536 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
537 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
538 $( $rest:tt )*
539 ) => {
540 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
541 morph_types! {
542 @IMPL $name $( < $( $bound_id ),* > )? :
543 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
544 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
545 = |$var: $var_type| -> $outcome { $( $ex )* }
546 }
547 morph_types!{ $($rest)* }
548 };
549 (
550 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
551 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
552 $( EXTRA_GENERIC ($extra:ident) )?
553 : TryMorph
554 = |$var:ident: $var_type:ty| -> Result<$outcome:ty, ()> { $( $ex:expr )* }
555 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
556 $( $rest:tt )*
557 ) => {
558 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
559 morph_types! {
560 @IMPL_TRY $name $( < $( $bound_id ),* > )? :
561 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
562 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
563 = |$var: $var_type| -> $outcome { $( $ex )* }
564 }
565 morph_types!{ $($rest)* }
566 };
567 () => {}
568}
569
570morph_types! {
571 pub type Replace<V: TypedGet> = |_| -> V::Type { V::get() };
573
574 pub type ReplaceWithDefault<V: Default> = |_| -> V { Default::default() };
576
577 pub type ReduceBy<N: TypedGet> = |r: N::Type| -> N::Type {
579 r.checked_sub(&N::get()).unwrap_or(Zero::zero())
580 } where N::Type: CheckedSub | Zero;
581
582 pub type CheckedReduceBy<N: TypedGet>: TryMorph = |r: N::Type| -> Result<N::Type, ()> {
585 r.checked_sub(&N::get()).ok_or(())
586 } where N::Type: CheckedSub;
587
588 pub type MorphWithUpperLimit<L: TypedGet, M>: TryMorph = |r: L::Type| -> Result<L::Type, ()> {
590 M::try_morph(r).map(|m| m.min(L::get()))
591 } where L::Type: Ord, M: TryMorph<L::Type, Outcome = L::Type>;
592}
593
594pub trait Convert<A, B> {
596 fn convert(a: A) -> B;
598}
599
600impl<A, B: Default> Convert<A, B> for () {
601 fn convert(_: A) -> B {
602 Default::default()
603 }
604}
605
606pub trait ConvertBack<A, B>: Convert<A, B> {
610 fn convert_back(b: B) -> A;
612}
613
614pub trait MaybeConvert<A, B> {
616 fn maybe_convert(a: A) -> Option<B>;
618}
619
620#[impl_trait_for_tuples::impl_for_tuples(30)]
621impl<A: Clone, B> MaybeConvert<A, B> for Tuple {
622 fn maybe_convert(a: A) -> Option<B> {
623 for_tuples!( #(
624 match Tuple::maybe_convert(a.clone()) {
625 Some(b) => return Some(b),
626 None => {},
627 }
628 )* );
629 None
630 }
631}
632
633pub trait MaybeConvertBack<A, B>: MaybeConvert<A, B> {
636 fn maybe_convert_back(b: B) -> Option<A>;
638}
639
640#[impl_trait_for_tuples::impl_for_tuples(30)]
641impl<A: Clone, B: Clone> MaybeConvertBack<A, B> for Tuple {
642 fn maybe_convert_back(b: B) -> Option<A> {
643 for_tuples!( #(
644 match Tuple::maybe_convert_back(b.clone()) {
645 Some(a) => return Some(a),
646 None => {},
647 }
648 )* );
649 None
650 }
651}
652
653pub trait TryConvert<A, B> {
656 fn try_convert(a: A) -> Result<B, A>;
658}
659
660#[impl_trait_for_tuples::impl_for_tuples(30)]
661impl<A, B> TryConvert<A, B> for Tuple {
662 fn try_convert(a: A) -> Result<B, A> {
663 for_tuples!( #(
664 let a = match Tuple::try_convert(a) {
665 Ok(b) => return Ok(b),
666 Err(a) => a,
667 };
668 )* );
669 Err(a)
670 }
671}
672
673pub trait TryConvertBack<A, B>: TryConvert<A, B> {
676 fn try_convert_back(b: B) -> Result<A, B>;
679}
680
681#[impl_trait_for_tuples::impl_for_tuples(30)]
682impl<A, B> TryConvertBack<A, B> for Tuple {
683 fn try_convert_back(b: B) -> Result<A, B> {
684 for_tuples!( #(
685 let b = match Tuple::try_convert_back(b) {
686 Ok(a) => return Ok(a),
687 Err(b) => b,
688 };
689 )* );
690 Err(b)
691 }
692}
693
694pub trait MaybeEquivalence<A, B> {
696 fn convert(a: &A) -> Option<B>;
698 fn convert_back(b: &B) -> Option<A>;
700}
701
702#[impl_trait_for_tuples::impl_for_tuples(30)]
703impl<A, B> MaybeEquivalence<A, B> for Tuple {
704 fn convert(a: &A) -> Option<B> {
705 for_tuples!( #(
706 match Tuple::convert(a) {
707 Some(b) => return Some(b),
708 None => {},
709 }
710 )* );
711 None
712 }
713 fn convert_back(b: &B) -> Option<A> {
714 for_tuples!( #(
715 match Tuple::convert_back(b) {
716 Some(a) => return Some(a),
717 None => {},
718 }
719 )* );
720 None
721 }
722}
723
724pub struct ConvertToValue<T>(core::marker::PhantomData<T>);
727impl<X, Y, T: Get<Y>> Convert<X, Y> for ConvertToValue<T> {
728 fn convert(_: X) -> Y {
729 T::get()
730 }
731}
732impl<X, Y, T: Get<Y>> MaybeConvert<X, Y> for ConvertToValue<T> {
733 fn maybe_convert(_: X) -> Option<Y> {
734 Some(T::get())
735 }
736}
737impl<X, Y, T: Get<Y>> MaybeConvertBack<X, Y> for ConvertToValue<T> {
738 fn maybe_convert_back(_: Y) -> Option<X> {
739 None
740 }
741}
742impl<X, Y, T: Get<Y>> TryConvert<X, Y> for ConvertToValue<T> {
743 fn try_convert(_: X) -> Result<Y, X> {
744 Ok(T::get())
745 }
746}
747impl<X, Y, T: Get<Y>> TryConvertBack<X, Y> for ConvertToValue<T> {
748 fn try_convert_back(y: Y) -> Result<X, Y> {
749 Err(y)
750 }
751}
752impl<X, Y, T: Get<Y>> MaybeEquivalence<X, Y> for ConvertToValue<T> {
753 fn convert(_: &X) -> Option<Y> {
754 Some(T::get())
755 }
756 fn convert_back(_: &Y) -> Option<X> {
757 None
758 }
759}
760
761pub struct Identity;
763impl<T> Convert<T, T> for Identity {
764 fn convert(a: T) -> T {
765 a
766 }
767}
768impl<T> ConvertBack<T, T> for Identity {
769 fn convert_back(a: T) -> T {
770 a
771 }
772}
773impl<T> MaybeConvert<T, T> for Identity {
774 fn maybe_convert(a: T) -> Option<T> {
775 Some(a)
776 }
777}
778impl<T> MaybeConvertBack<T, T> for Identity {
779 fn maybe_convert_back(a: T) -> Option<T> {
780 Some(a)
781 }
782}
783impl<T> TryConvert<T, T> for Identity {
784 fn try_convert(a: T) -> Result<T, T> {
785 Ok(a)
786 }
787}
788impl<T> TryConvertBack<T, T> for Identity {
789 fn try_convert_back(a: T) -> Result<T, T> {
790 Ok(a)
791 }
792}
793impl<T: Clone> MaybeEquivalence<T, T> for Identity {
794 fn convert(a: &T) -> Option<T> {
795 Some(a.clone())
796 }
797 fn convert_back(a: &T) -> Option<T> {
798 Some(a.clone())
799 }
800}
801
802pub struct ConvertInto;
804impl<A: Into<B>, B> Convert<A, B> for ConvertInto {
805 fn convert(a: A) -> B {
806 a.into()
807 }
808}
809impl<A: Into<B>, B> MaybeConvert<A, B> for ConvertInto {
810 fn maybe_convert(a: A) -> Option<B> {
811 Some(a.into())
812 }
813}
814impl<A: Into<B>, B: Into<A>> MaybeConvertBack<A, B> for ConvertInto {
815 fn maybe_convert_back(b: B) -> Option<A> {
816 Some(b.into())
817 }
818}
819impl<A: Into<B>, B> TryConvert<A, B> for ConvertInto {
820 fn try_convert(a: A) -> Result<B, A> {
821 Ok(a.into())
822 }
823}
824impl<A: Into<B>, B: Into<A>> TryConvertBack<A, B> for ConvertInto {
825 fn try_convert_back(b: B) -> Result<A, B> {
826 Ok(b.into())
827 }
828}
829impl<A: Clone + Into<B>, B: Clone + Into<A>> MaybeEquivalence<A, B> for ConvertInto {
830 fn convert(a: &A) -> Option<B> {
831 Some(a.clone().into())
832 }
833 fn convert_back(b: &B) -> Option<A> {
834 Some(b.clone().into())
835 }
836}
837
838pub struct TryConvertInto;
840impl<A: Clone + TryInto<B>, B> MaybeConvert<A, B> for TryConvertInto {
841 fn maybe_convert(a: A) -> Option<B> {
842 a.clone().try_into().ok()
843 }
844}
845impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeConvertBack<A, B> for TryConvertInto {
846 fn maybe_convert_back(b: B) -> Option<A> {
847 b.clone().try_into().ok()
848 }
849}
850impl<A: Clone + TryInto<B>, B> TryConvert<A, B> for TryConvertInto {
851 fn try_convert(a: A) -> Result<B, A> {
852 a.clone().try_into().map_err(|_| a)
853 }
854}
855impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> TryConvertBack<A, B> for TryConvertInto {
856 fn try_convert_back(b: B) -> Result<A, B> {
857 b.clone().try_into().map_err(|_| b)
858 }
859}
860impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeEquivalence<A, B> for TryConvertInto {
861 fn convert(a: &A) -> Option<B> {
862 a.clone().try_into().ok()
863 }
864 fn convert_back(b: &B) -> Option<A> {
865 b.clone().try_into().ok()
866 }
867}
868
869pub trait CheckedConversion {
873 fn checked_from<T>(t: T) -> Option<Self>
879 where
880 Self: TryFrom<T>,
881 {
882 <Self as TryFrom<T>>::try_from(t).ok()
883 }
884 fn checked_into<T>(self) -> Option<T>
890 where
891 Self: TryInto<T>,
892 {
893 <Self as TryInto<T>>::try_into(self).ok()
894 }
895}
896impl<T: Sized> CheckedConversion for T {}
897
898pub trait Scale<Other> {
901 type Output;
903
904 fn mul(self, other: Other) -> Self::Output;
906
907 fn div(self, other: Other) -> Self::Output;
909
910 fn rem(self, other: Other) -> Self::Output;
912}
913macro_rules! impl_scale {
914 ($self:ty, $other:ty) => {
915 impl Scale<$other> for $self {
916 type Output = Self;
917 fn mul(self, other: $other) -> Self::Output {
918 self * (other as Self)
919 }
920 fn div(self, other: $other) -> Self::Output {
921 self / (other as Self)
922 }
923 fn rem(self, other: $other) -> Self::Output {
924 self % (other as Self)
925 }
926 }
927 };
928}
929impl_scale!(u128, u128);
930impl_scale!(u128, u64);
931impl_scale!(u128, u32);
932impl_scale!(u128, u16);
933impl_scale!(u128, u8);
934impl_scale!(u64, u64);
935impl_scale!(u64, u32);
936impl_scale!(u64, u16);
937impl_scale!(u64, u8);
938impl_scale!(u32, u32);
939impl_scale!(u32, u16);
940impl_scale!(u32, u8);
941impl_scale!(u16, u16);
942impl_scale!(u16, u8);
943impl_scale!(u8, u8);
944
945pub trait Clear {
948 fn is_clear(&self) -> bool;
950
951 fn clear() -> Self;
953}
954
955impl<T: Default + Eq + PartialEq> Clear for T {
956 fn is_clear(&self) -> bool {
957 *self == Self::clear()
958 }
959 fn clear() -> Self {
960 Default::default()
961 }
962}
963
964pub trait SimpleBitOps:
966 Sized
967 + Clear
968 + core::ops::BitOr<Self, Output = Self>
969 + core::ops::BitXor<Self, Output = Self>
970 + core::ops::BitAnd<Self, Output = Self>
971{
972}
973impl<
974 T: Sized
975 + Clear
976 + core::ops::BitOr<Self, Output = Self>
977 + core::ops::BitXor<Self, Output = Self>
978 + core::ops::BitAnd<Self, Output = Self>,
979 > SimpleBitOps for T
980{
981}
982
983pub trait Hash:
987 'static
988 + MaybeSerializeDeserialize
989 + Debug
990 + Clone
991 + Eq
992 + PartialEq
993 + Hasher<Out = <Self as Hash>::Output>
994{
995 type Output: HashOutput;
997
998 fn hash(s: &[u8]) -> Self::Output {
1000 <Self as Hasher>::hash(s)
1001 }
1002
1003 fn hash_of<S: Encode>(s: &S) -> Self::Output {
1005 Encode::using_encoded(s, <Self as Hasher>::hash)
1006 }
1007
1008 fn ordered_trie_root(input: Vec<Vec<u8>>, state_version: StateVersion) -> Self::Output;
1010
1011 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, state_version: StateVersion) -> Self::Output;
1013}
1014
1015pub trait HashOutput:
1017 Member
1018 + MaybeSerializeDeserialize
1019 + MaybeDisplay
1020 + MaybeFromStr
1021 + Debug
1022 + core::hash::Hash
1023 + AsRef<[u8]>
1024 + AsMut<[u8]>
1025 + Copy
1026 + Ord
1027 + Default
1028 + Encode
1029 + Decode
1030 + DecodeWithMemTracking
1031 + EncodeLike
1032 + MaxEncodedLen
1033 + TypeInfo
1034{
1035}
1036
1037impl<T> HashOutput for T where
1038 T: Member
1039 + MaybeSerializeDeserialize
1040 + MaybeDisplay
1041 + MaybeFromStr
1042 + Debug
1043 + core::hash::Hash
1044 + AsRef<[u8]>
1045 + AsMut<[u8]>
1046 + Copy
1047 + Ord
1048 + Default
1049 + Encode
1050 + Decode
1051 + DecodeWithMemTracking
1052 + EncodeLike
1053 + MaxEncodedLen
1054 + TypeInfo
1055{
1056}
1057
1058#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1061pub struct BlakeTwo256;
1062
1063impl Hasher for BlakeTwo256 {
1064 type Out = sp_core::H256;
1065 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1066 const LENGTH: usize = 32;
1067
1068 fn hash(s: &[u8]) -> Self::Out {
1069 sp_io::hashing::blake2_256(s).into()
1070 }
1071}
1072
1073impl Hash for BlakeTwo256 {
1074 type Output = sp_core::H256;
1075
1076 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1077 sp_io::trie::blake2_256_ordered_root(input, version)
1078 }
1079
1080 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1081 sp_io::trie::blake2_256_root(input, version)
1082 }
1083}
1084
1085#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1087#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1088pub struct Keccak256;
1089
1090impl Hasher for Keccak256 {
1091 type Out = sp_core::H256;
1092 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1093 const LENGTH: usize = 32;
1094
1095 fn hash(s: &[u8]) -> Self::Out {
1096 sp_io::hashing::keccak_256(s).into()
1097 }
1098}
1099
1100impl Hash for Keccak256 {
1101 type Output = sp_core::H256;
1102
1103 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1104 sp_io::trie::keccak_256_ordered_root(input, version)
1105 }
1106
1107 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1108 sp_io::trie::keccak_256_root(input, version)
1109 }
1110}
1111
1112pub trait CheckEqual {
1114 fn check_equal(&self, other: &Self);
1116}
1117
1118impl CheckEqual for sp_core::H256 {
1119 #[cfg(feature = "std")]
1120 fn check_equal(&self, other: &Self) {
1121 use sp_core::hexdisplay::HexDisplay;
1122 if self != other {
1123 println!(
1124 "Hash: given={}, expected={}",
1125 HexDisplay::from(self.as_fixed_bytes()),
1126 HexDisplay::from(other.as_fixed_bytes()),
1127 );
1128 }
1129 }
1130
1131 #[cfg(not(feature = "std"))]
1132 fn check_equal(&self, other: &Self) {
1133 if self != other {
1134 "Hash not equal".print();
1135 self.as_bytes().print();
1136 other.as_bytes().print();
1137 }
1138 }
1139}
1140
1141impl CheckEqual for super::generic::DigestItem {
1142 #[cfg(feature = "std")]
1143 fn check_equal(&self, other: &Self) {
1144 if self != other {
1145 println!("DigestItem: given={:?}, expected={:?}", self, other);
1146 }
1147 }
1148
1149 #[cfg(not(feature = "std"))]
1150 fn check_equal(&self, other: &Self) {
1151 if self != other {
1152 "DigestItem not equal".print();
1153 (&Encode::encode(self)[..]).print();
1154 (&Encode::encode(other)[..]).print();
1155 }
1156 }
1157}
1158
1159sp_core::impl_maybe_marker!(
1160 trait MaybeDisplay: Display;
1162
1163 trait MaybeFromStr: FromStr;
1165
1166 trait MaybeHash: core::hash::Hash;
1168);
1169
1170sp_core::impl_maybe_marker_std_or_serde!(
1171 trait MaybeSerialize: Serialize;
1173
1174 trait MaybeSerializeDeserialize: DeserializeOwned, Serialize;
1176);
1177
1178pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {}
1180impl<T: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static> Member for T {}
1181
1182pub trait IsMember<MemberId> {
1184 fn is_member(member_id: &MemberId) -> bool;
1186}
1187
1188pub trait BlockNumber:
1190 Member
1191 + MaybeSerializeDeserialize
1192 + MaybeFromStr
1193 + Debug
1194 + core::hash::Hash
1195 + Copy
1196 + MaybeDisplay
1197 + AtLeast32BitUnsigned
1198 + Into<U256>
1199 + TryFrom<U256>
1200 + Default
1201 + TypeInfo
1202 + MaxEncodedLen
1203 + FullCodec
1204 + DecodeWithMemTracking
1205 + HasCompact<Type: DecodeWithMemTracking>
1206{
1207}
1208
1209impl<
1210 T: Member
1211 + MaybeSerializeDeserialize
1212 + MaybeFromStr
1213 + Debug
1214 + core::hash::Hash
1215 + Copy
1216 + MaybeDisplay
1217 + AtLeast32BitUnsigned
1218 + Into<U256>
1219 + TryFrom<U256>
1220 + Default
1221 + TypeInfo
1222 + MaxEncodedLen
1223 + FullCodec
1224 + DecodeWithMemTracking
1225 + HasCompact<Type: DecodeWithMemTracking>,
1226 > BlockNumber for T
1227{
1228}
1229
1230pub trait Header:
1236 Clone
1237 + Send
1238 + Sync
1239 + Codec
1240 + DecodeWithMemTracking
1241 + Eq
1242 + MaybeSerialize
1243 + Debug
1244 + TypeInfo
1245 + 'static
1246{
1247 type Number: BlockNumber;
1249 type Hash: HashOutput;
1251 type Hashing: Hash<Output = Self::Hash>;
1253
1254 fn new(
1256 number: Self::Number,
1257 extrinsics_root: Self::Hash,
1258 state_root: Self::Hash,
1259 parent_hash: Self::Hash,
1260 digest: Digest,
1261 ) -> Self;
1262
1263 fn number(&self) -> &Self::Number;
1265 fn set_number(&mut self, number: Self::Number);
1267
1268 fn extrinsics_root(&self) -> &Self::Hash;
1270 fn set_extrinsics_root(&mut self, root: Self::Hash);
1272
1273 fn state_root(&self) -> &Self::Hash;
1275 fn set_state_root(&mut self, root: Self::Hash);
1277
1278 fn parent_hash(&self) -> &Self::Hash;
1280 fn set_parent_hash(&mut self, hash: Self::Hash);
1282
1283 fn digest(&self) -> &Digest;
1285 fn digest_mut(&mut self) -> &mut Digest;
1287
1288 fn hash(&self) -> Self::Hash {
1290 <Self::Hashing as Hash>::hash_of(self)
1291 }
1292}
1293
1294#[doc(hidden)]
1314pub trait HeaderProvider {
1315 type HeaderT: Header;
1317}
1318
1319pub trait LazyExtrinsic: Sized {
1321 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error>;
1329}
1330
1331pub trait LazyBlock: Debug + Encode + Decode + Sized {
1333 type Extrinsic: LazyExtrinsic;
1335 type Header: Header;
1337
1338 fn header(&self) -> &Self::Header;
1340
1341 fn header_mut(&mut self) -> &mut Self::Header;
1343
1344 fn extrinsics(&self) -> impl Iterator<Item = Result<Self::Extrinsic, codec::Error>>;
1348}
1349
1350pub trait Block:
1355 HeaderProvider<HeaderT = Self::Header>
1356 + Into<Self::LazyBlock>
1357 + EncodeLike<Self::LazyBlock>
1358 + Clone
1359 + Send
1360 + Sync
1361 + Codec
1362 + DecodeWithMemTracking
1363 + Eq
1364 + MaybeSerialize
1365 + Debug
1366 + 'static
1367{
1368 type Extrinsic: Member + Codec + ExtrinsicLike + MaybeSerialize + Into<OpaqueExtrinsic>;
1370 type Header: Header<Hash = Self::Hash> + MaybeSerializeDeserialize;
1372 type Hash: HashOutput;
1374
1375 type LazyBlock: LazyBlock<Extrinsic = Self::Extrinsic, Header = Self::Header> + EncodeLike<Self>;
1378
1379 fn header(&self) -> &Self::Header;
1381 fn extrinsics(&self) -> &[Self::Extrinsic];
1383 fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>);
1385 fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self;
1387 fn hash(&self) -> Self::Hash {
1389 <<Self::Header as Header>::Hashing as Hash>::hash_of(self.header())
1390 }
1391}
1392
1393#[deprecated = "Use `ExtrinsicLike` along with the `CreateTransaction` trait family instead"]
1395pub trait Extrinsic: Sized {
1396 type Call: TypeInfo;
1398
1399 type SignaturePayload: SignaturePayload;
1405
1406 fn is_signed(&self) -> Option<bool> {
1409 None
1410 }
1411
1412 fn is_bare(&self) -> bool {
1414 !self.is_signed().unwrap_or(true)
1415 }
1416
1417 fn new(_call: Self::Call, _signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
1420 None
1421 }
1422}
1423
1424pub trait ExtrinsicLike: Sized {
1426 #[deprecated = "Use and implement `!is_bare()` instead"]
1429 fn is_signed(&self) -> Option<bool> {
1430 None
1431 }
1432
1433 fn is_bare(&self) -> bool {
1435 #[allow(deprecated)]
1436 !self.is_signed().unwrap_or(true)
1437 }
1438}
1439
1440#[allow(deprecated)]
1441impl<T> ExtrinsicLike for T
1442where
1443 T: Extrinsic,
1444{
1445 fn is_signed(&self) -> Option<bool> {
1446 #[allow(deprecated)]
1447 <Self as Extrinsic>::is_signed(&self)
1448 }
1449
1450 fn is_bare(&self) -> bool {
1451 <Self as Extrinsic>::is_bare(&self)
1452 }
1453}
1454
1455pub trait ExtrinsicCall: ExtrinsicLike {
1457 type Call;
1459
1460 fn call(&self) -> &Self::Call;
1462
1463 fn into_call(self) -> Self::Call;
1465}
1466
1467pub trait SignaturePayload {
1470 type SignatureAddress: TypeInfo;
1474
1475 type Signature: TypeInfo;
1479
1480 type SignatureExtra: TypeInfo;
1484}
1485
1486impl SignaturePayload for () {
1487 type SignatureAddress = ();
1488 type Signature = ();
1489 type SignatureExtra = ();
1490}
1491
1492pub trait ExtrinsicMetadata {
1494 const VERSIONS: &'static [u8];
1498
1499 type TransactionExtensions;
1501}
1502
1503pub type HashingFor<B> = <<B as Block>::Header as Header>::Hashing;
1505pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
1507pub trait Checkable<Context>: Sized {
1514 type Checked;
1516
1517 fn check(self, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
1519
1520 #[cfg(feature = "try-runtime")]
1529 fn unchecked_into_checked_i_know_what_i_am_doing(
1530 self,
1531 c: &Context,
1532 ) -> Result<Self::Checked, TransactionValidityError>;
1533}
1534
1535pub trait BlindCheckable: Sized {
1540 type Checked;
1542
1543 fn check(self) -> Result<Self::Checked, TransactionValidityError>;
1545}
1546
1547impl<T: BlindCheckable, Context> Checkable<Context> for T {
1549 type Checked = <Self as BlindCheckable>::Checked;
1550
1551 fn check(self, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
1552 BlindCheckable::check(self)
1553 }
1554
1555 #[cfg(feature = "try-runtime")]
1556 fn unchecked_into_checked_i_know_what_i_am_doing(
1557 self,
1558 _: &Context,
1559 ) -> Result<Self::Checked, TransactionValidityError> {
1560 unreachable!();
1561 }
1562}
1563
1564pub trait RefundWeight {
1566 fn refund(&mut self, weight: sp_weights::Weight);
1568}
1569
1570pub trait ExtensionPostDispatchWeightHandler<DispatchInfo>: RefundWeight {
1573 fn set_extension_weight(&mut self, info: &DispatchInfo);
1575}
1576
1577impl RefundWeight for () {
1578 fn refund(&mut self, _weight: sp_weights::Weight) {}
1579}
1580
1581impl ExtensionPostDispatchWeightHandler<()> for () {
1582 fn set_extension_weight(&mut self, _info: &()) {}
1583}
1584
1585pub trait Dispatchable {
1588 type RuntimeOrigin: Debug;
1592 type Config;
1594 type Info;
1598 type PostInfo: Eq
1601 + PartialEq
1602 + Clone
1603 + Copy
1604 + Encode
1605 + Decode
1606 + Printable
1607 + ExtensionPostDispatchWeightHandler<Self::Info>;
1608 fn dispatch(self, origin: Self::RuntimeOrigin)
1610 -> crate::DispatchResultWithInfo<Self::PostInfo>;
1611}
1612
1613pub type DispatchOriginOf<T> = <T as Dispatchable>::RuntimeOrigin;
1615pub type DispatchInfoOf<T> = <T as Dispatchable>::Info;
1617pub type PostDispatchInfoOf<T> = <T as Dispatchable>::PostInfo;
1619
1620impl Dispatchable for () {
1621 type RuntimeOrigin = ();
1622 type Config = ();
1623 type Info = ();
1624 type PostInfo = ();
1625 fn dispatch(
1626 self,
1627 _origin: Self::RuntimeOrigin,
1628 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1629 panic!("This implementation should not be used for actual dispatch.");
1630 }
1631}
1632
1633#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
1635pub struct FakeDispatchable<Inner>(pub Inner);
1636impl<Inner> From<Inner> for FakeDispatchable<Inner> {
1637 fn from(inner: Inner) -> Self {
1638 Self(inner)
1639 }
1640}
1641impl<Inner> FakeDispatchable<Inner> {
1642 pub fn deconstruct(self) -> Inner {
1644 self.0
1645 }
1646}
1647impl<Inner> AsRef<Inner> for FakeDispatchable<Inner> {
1648 fn as_ref(&self) -> &Inner {
1649 &self.0
1650 }
1651}
1652
1653impl<Inner> Dispatchable for FakeDispatchable<Inner> {
1654 type RuntimeOrigin = ();
1655 type Config = ();
1656 type Info = ();
1657 type PostInfo = ();
1658 fn dispatch(
1659 self,
1660 _origin: Self::RuntimeOrigin,
1661 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1662 panic!("This implementation should not be used for actual dispatch.");
1663 }
1664}
1665
1666pub trait AsSystemOriginSigner<AccountId> {
1668 fn as_system_origin_signer(&self) -> Option<&AccountId>;
1671}
1672
1673pub trait AsTransactionAuthorizedOrigin {
1687 fn is_transaction_authorized(&self) -> bool;
1697}
1698
1699#[deprecated = "Use `TransactionExtension` instead."]
1702pub trait SignedExtension:
1703 Codec + DecodeWithMemTracking + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
1704{
1705 const IDENTIFIER: &'static str;
1710
1711 type AccountId;
1713
1714 type Call: Dispatchable;
1716
1717 type AdditionalSigned: Codec + TypeInfo;
1720
1721 type Pre;
1723
1724 fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError>;
1727
1728 fn validate(
1738 &self,
1739 _who: &Self::AccountId,
1740 _call: &Self::Call,
1741 _info: &DispatchInfoOf<Self::Call>,
1742 _len: usize,
1743 ) -> TransactionValidity {
1744 Ok(ValidTransaction::default())
1745 }
1746
1747 fn pre_dispatch(
1751 self,
1752 who: &Self::AccountId,
1753 call: &Self::Call,
1754 info: &DispatchInfoOf<Self::Call>,
1755 len: usize,
1756 ) -> Result<Self::Pre, TransactionValidityError>;
1757
1758 fn post_dispatch(
1775 _pre: Option<Self::Pre>,
1776 _info: &DispatchInfoOf<Self::Call>,
1777 _post_info: &PostDispatchInfoOf<Self::Call>,
1778 _len: usize,
1779 _result: &DispatchResult,
1780 ) -> Result<(), TransactionValidityError> {
1781 Ok(())
1782 }
1783
1784 fn metadata() -> Vec<TransactionExtensionMetadata> {
1793 alloc::vec![TransactionExtensionMetadata {
1794 identifier: Self::IDENTIFIER,
1795 ty: scale_info::meta_type::<Self>(),
1796 implicit: scale_info::meta_type::<Self::AdditionalSigned>()
1797 }]
1798 }
1799
1800 fn validate_unsigned(
1807 _call: &Self::Call,
1808 _info: &DispatchInfoOf<Self::Call>,
1809 _len: usize,
1810 ) -> TransactionValidity {
1811 Ok(ValidTransaction::default())
1812 }
1813
1814 fn pre_dispatch_unsigned(
1823 call: &Self::Call,
1824 info: &DispatchInfoOf<Self::Call>,
1825 len: usize,
1826 ) -> Result<(), TransactionValidityError> {
1827 Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into)
1828 }
1829}
1830
1831pub trait Applyable: Sized + Send + Sync {
1847 type Call: Dispatchable;
1849
1850 fn validate<V: ValidateUnsigned<Call = Self::Call>>(
1855 &self,
1856 source: TransactionSource,
1857 info: &DispatchInfoOf<Self::Call>,
1858 len: usize,
1859 ) -> TransactionValidity;
1860
1861 fn apply<V: ValidateUnsigned<Call = Self::Call>>(
1867 self,
1868 info: &DispatchInfoOf<Self::Call>,
1869 len: usize,
1870 ) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>>;
1871}
1872
1873pub trait GetRuntimeBlockType {
1875 type RuntimeBlock: self::Block;
1877}
1878
1879pub trait GetNodeBlockType {
1881 type NodeBlock: self::Block;
1883}
1884
1885pub trait ValidateUnsigned {
1893 type Call;
1895
1896 fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
1909 Self::validate_unsigned(TransactionSource::InBlock, call)
1910 .map(|_| ())
1911 .map_err(Into::into)
1912 }
1913
1914 fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity;
1927}
1928
1929pub trait OpaqueKeys: Clone {
1932 type KeyTypeIdProviders;
1936
1937 fn key_ids() -> &'static [KeyTypeId];
1939
1940 fn get_raw(&self, i: KeyTypeId) -> &[u8];
1942
1943 fn get<T: Decode>(&self, i: KeyTypeId) -> Option<T> {
1945 T::decode(&mut self.get_raw(i)).ok()
1946 }
1947
1948 #[must_use]
1950 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool;
1951}
1952
1953pub struct AppendZerosInput<'a, T>(&'a mut T);
1958
1959impl<'a, T> AppendZerosInput<'a, T> {
1960 pub fn new(input: &'a mut T) -> Self {
1962 Self(input)
1963 }
1964}
1965
1966impl<'a, T: codec::Input> codec::Input for AppendZerosInput<'a, T> {
1967 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
1968 Ok(None)
1969 }
1970
1971 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
1972 let remaining = self.0.remaining_len()?;
1973 let completed = if let Some(n) = remaining {
1974 let readable = into.len().min(n);
1975 self.0.read(&mut into[..readable])?;
1977 readable
1978 } else {
1979 let mut i = 0;
1981 while i < into.len() {
1982 if let Ok(b) = self.0.read_byte() {
1983 into[i] = b;
1984 i += 1;
1985 } else {
1986 break
1987 }
1988 }
1989 i
1990 };
1991 for i in &mut into[completed..] {
1993 *i = 0;
1994 }
1995 Ok(())
1996 }
1997}
1998
1999pub struct TrailingZeroInput<'a>(&'a [u8]);
2001
2002impl<'a> TrailingZeroInput<'a> {
2003 pub fn new(data: &'a [u8]) -> Self {
2005 Self(data)
2006 }
2007
2008 pub fn zeroes() -> Self {
2010 Self::new(&[][..])
2011 }
2012}
2013
2014impl<'a> codec::Input for TrailingZeroInput<'a> {
2015 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
2016 Ok(None)
2017 }
2018
2019 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
2020 let len_from_inner = into.len().min(self.0.len());
2021 into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]);
2022 for i in &mut into[len_from_inner..] {
2023 *i = 0;
2024 }
2025 self.0 = &self.0[len_from_inner..];
2026
2027 Ok(())
2028 }
2029}
2030
2031pub trait AccountIdConversion<AccountId>: Sized {
2033 fn into_account_truncating(&self) -> AccountId {
2036 self.into_sub_account_truncating(&())
2037 }
2038
2039 fn try_into_account(&self) -> Option<AccountId> {
2042 self.try_into_sub_account(&())
2043 }
2044
2045 fn try_from_account(a: &AccountId) -> Option<Self> {
2047 Self::try_from_sub_account::<()>(a).map(|x| x.0)
2048 }
2049
2050 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> AccountId;
2064
2065 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<AccountId>;
2069
2070 fn try_from_sub_account<S: Decode>(x: &AccountId) -> Option<(Self, S)>;
2072}
2073
2074impl<T: Encode + Decode, Id: Encode + Decode + TypeId> AccountIdConversion<T> for Id {
2077 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> T {
2081 (Id::TYPE_ID, self, sub)
2082 .using_encoded(|b| T::decode(&mut TrailingZeroInput(b)))
2083 .expect("All byte sequences are valid `AccountIds`; qed")
2084 }
2085
2086 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<T> {
2088 let encoded_seed = (Id::TYPE_ID, self, sub).encode();
2089 let account = T::decode(&mut TrailingZeroInput(&encoded_seed))
2090 .expect("All byte sequences are valid `AccountIds`; qed");
2091 if encoded_seed.len() <= account.encoded_size() {
2094 Some(account)
2095 } else {
2096 None
2097 }
2098 }
2099
2100 fn try_from_sub_account<S: Decode>(x: &T) -> Option<(Self, S)> {
2101 x.using_encoded(|d| {
2102 if d[0..4] != Id::TYPE_ID {
2103 return None
2104 }
2105 let mut cursor = &d[4..];
2106 let result = Decode::decode(&mut cursor).ok()?;
2107 if cursor.iter().all(|x| *x == 0) {
2108 Some(result)
2109 } else {
2110 None
2111 }
2112 })
2113 }
2114}
2115
2116#[macro_export]
2123macro_rules! count {
2124 ($f:ident ($($x:tt)*) ) => ();
2125 ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); };
2126 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); };
2127 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); };
2128 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => {
2129 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3);
2130 };
2131 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => {
2132 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4);
2133 };
2134}
2135
2136#[doc(hidden)]
2137#[macro_export]
2138macro_rules! impl_opaque_keys_inner {
2139 (
2140 $( #[ $attr:meta ] )*
2141 pub struct $name:ident {
2142 $(
2143 $( #[ $inner_attr:meta ] )*
2144 pub $field:ident: $type:ty,
2145 )*
2146 },
2147 $crate_path:path,
2148 ) => {
2149 $( #[ $attr ] )*
2150 #[doc = concat!("Generated by [`impl_opaque_keys!`](", stringify!($crate_path),"::impl_opaque_keys).")]
2152 #[derive(
2153 Clone, PartialEq, Eq,
2154 $crate::codec::Encode,
2155 $crate::codec::Decode,
2156 $crate::codec::DecodeWithMemTracking,
2157 $crate::scale_info::TypeInfo,
2158 Debug,
2159 )]
2160 pub struct $name {
2161 $(
2162 $( #[ $inner_attr ] )*
2163 pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public,
2164 )*
2165 }
2166
2167 impl $name {
2168 #[allow(dead_code)]
2181 pub fn generate(
2182 owner: &[u8],
2183 seed: Option<$crate::sp_std::vec::Vec<u8>>,
2184 ) -> $crate::traits::GeneratedSessionKeys<
2185 Self,
2186 (
2187 $(
2188 <
2189 <$type as $crate::BoundToRuntimeAppPublic>::Public
2190 as $crate::RuntimeAppPublic
2191 >::ProofOfPossession
2192 ),*
2193 )
2194 > {
2195 let mut keys = Self {
2196 $(
2197 $field: <
2198 <
2199 $type as $crate::BoundToRuntimeAppPublic
2200 >::Public as $crate::RuntimeAppPublic
2201 >::generate_pair(seed.clone()),
2202 )*
2203 };
2204
2205 let proof = keys.create_ownership_proof(owner)
2206 .expect("Private key that was generated a moment ago, should exist; qed");
2207
2208 $crate::traits::GeneratedSessionKeys {
2209 keys,
2210 proof
2211 }
2212 }
2213
2214 #[allow(dead_code)]
2216 pub fn into_raw_public_keys(
2217 self,
2218 ) -> $crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)> {
2219 let mut keys = Vec::new();
2220 $(
2221 keys.push((
2222 $crate::RuntimeAppPublic::to_raw_vec(&self.$field),
2223 <
2224 <
2225 $type as $crate::BoundToRuntimeAppPublic
2226 >::Public as $crate::RuntimeAppPublic
2227 >::ID,
2228 ));
2229 )*
2230
2231 keys
2232 }
2233
2234 #[allow(dead_code)]
2239 pub fn decode_into_raw_public_keys(
2240 encoded: &[u8],
2241 ) -> Option<$crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)>> {
2242 <Self as $crate::codec::Decode>::decode(&mut &encoded[..])
2243 .ok()
2244 .map(|s| s.into_raw_public_keys())
2245 }
2246
2247 #[allow(dead_code)]
2257 pub fn create_ownership_proof(
2258 &mut self,
2259 owner: &[u8],
2260 ) -> $crate::sp_std::result::Result<
2261 (
2262 $(
2263 <
2264 <$type as $crate::BoundToRuntimeAppPublic>::Public
2265 as $crate::RuntimeAppPublic
2266 >::ProofOfPossession
2267 ),*
2268 ),
2269 ()
2270 > {
2271 let res = ($(
2272 $crate::RuntimeAppPublic::generate_proof_of_possession(&mut self.$field, &owner).ok_or(())?
2273 ),*);
2274
2275 Ok(res)
2276 }
2277 }
2278
2279 impl $crate::traits::OpaqueKeys for $name {
2280 type KeyTypeIdProviders = ( $( $type, )* );
2281
2282 fn key_ids() -> &'static [$crate::KeyTypeId] {
2283 &[
2284 $(
2285 <
2286 <
2287 $type as $crate::BoundToRuntimeAppPublic
2288 >::Public as $crate::RuntimeAppPublic
2289 >::ID
2290 ),*
2291 ]
2292 }
2293
2294 fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] {
2295 match i {
2296 $(
2297 i if i == <
2298 <
2299 $type as $crate::BoundToRuntimeAppPublic
2300 >::Public as $crate::RuntimeAppPublic
2301 >::ID =>
2302 self.$field.as_ref(),
2303 )*
2304 _ => &[],
2305 }
2306 }
2307
2308 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool {
2309 let Ok(proof) = <($(
2311 <
2312 <
2313 $type as $crate::BoundToRuntimeAppPublic
2314 >::Public as $crate::RuntimeAppPublic
2315 >::ProofOfPossession
2316 ),*) as $crate::codec::DecodeAll>::decode_all(&mut &proof[..]) else {
2317 return false
2318 };
2319
2320 let ( $( $field ),* ) = proof;
2322
2323 $(
2325 let valid = $crate::RuntimeAppPublic::verify_proof_of_possession(&self.$field, &owner, &$field);
2326
2327 if !valid {
2328 return false
2330 }
2331 )*
2332
2333 true
2334 }
2335 }
2336 };
2337}
2338
2339#[derive(Debug, Clone, Encode, Decode, TypeInfo)]
2346pub struct GeneratedSessionKeys<Keys, Proof> {
2347 pub keys: Keys,
2349 pub proof: Proof,
2351}
2352
2353#[macro_export]
2383#[cfg(any(feature = "serde", feature = "std"))]
2384macro_rules! impl_opaque_keys {
2385 {
2386 $( #[ $attr:meta ] )*
2387 pub struct $name:ident {
2388 $(
2389 $( #[ $inner_attr:meta ] )*
2390 pub $field:ident: $type:ty,
2391 )*
2392 }
2393 } => {
2394 $crate::paste::paste! {
2395 use $crate::serde as [< __opaque_keys_serde_import__ $name >];
2396
2397 $crate::impl_opaque_keys_inner! {
2398 $( #[ $attr ] )*
2399 #[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
2400 #[serde(crate = "__opaque_keys_serde_import__" $name)]
2401 pub struct $name {
2402 $(
2403 $( #[ $inner_attr ] )*
2404 pub $field: $type,
2405 )*
2406 },
2407 $crate,
2408 }
2409 }
2410 }
2411}
2412
2413#[macro_export]
2414#[cfg(all(not(feature = "std"), not(feature = "serde")))]
2415#[doc(hidden)]
2416macro_rules! impl_opaque_keys {
2417 {
2418 $( #[ $attr:meta ] )*
2419 pub struct $name:ident {
2420 $(
2421 $( #[ $inner_attr:meta ] )*
2422 pub $field:ident: $type:ty,
2423 )*
2424 }
2425 } => {
2426 $crate::impl_opaque_keys_inner! {
2427 $( #[ $attr ] )*
2428 pub struct $name {
2429 $(
2430 $( #[ $inner_attr ] )*
2431 pub $field: $type,
2432 )*
2433 },
2434 $crate,
2435 }
2436 }
2437}
2438
2439pub trait Printable {
2441 fn print(&self);
2443}
2444
2445impl<T: Printable> Printable for &T {
2446 fn print(&self) {
2447 (*self).print()
2448 }
2449}
2450
2451impl Printable for u8 {
2452 fn print(&self) {
2453 (*self as u64).print()
2454 }
2455}
2456
2457impl Printable for u32 {
2458 fn print(&self) {
2459 (*self as u64).print()
2460 }
2461}
2462
2463impl Printable for usize {
2464 fn print(&self) {
2465 (*self as u64).print()
2466 }
2467}
2468
2469impl Printable for u64 {
2470 fn print(&self) {
2471 sp_io::misc::print_num(*self);
2472 }
2473}
2474
2475impl Printable for &[u8] {
2476 fn print(&self) {
2477 sp_io::misc::print_hex(self);
2478 }
2479}
2480
2481impl<const N: usize> Printable for [u8; N] {
2482 fn print(&self) {
2483 sp_io::misc::print_hex(&self[..]);
2484 }
2485}
2486
2487impl Printable for &str {
2488 fn print(&self) {
2489 sp_io::misc::print_utf8(self.as_bytes());
2490 }
2491}
2492
2493impl Printable for bool {
2494 fn print(&self) {
2495 if *self {
2496 "true".print()
2497 } else {
2498 "false".print()
2499 }
2500 }
2501}
2502
2503impl Printable for sp_weights::Weight {
2504 fn print(&self) {
2505 self.ref_time().print()
2506 }
2507}
2508
2509impl Printable for () {
2510 fn print(&self) {
2511 "()".print()
2512 }
2513}
2514
2515#[impl_for_tuples(1, 12)]
2516impl Printable for Tuple {
2517 fn print(&self) {
2518 for_tuples!( #( Tuple.print(); )* )
2519 }
2520}
2521
2522#[cfg(feature = "std")]
2524pub trait BlockIdTo<Block: self::Block> {
2525 type Error: std::error::Error;
2527
2528 fn to_hash(
2530 &self,
2531 block_id: &crate::generic::BlockId<Block>,
2532 ) -> Result<Option<Block::Hash>, Self::Error>;
2533
2534 fn to_number(
2536 &self,
2537 block_id: &crate::generic::BlockId<Block>,
2538 ) -> Result<Option<NumberFor<Block>>, Self::Error>;
2539}
2540
2541pub trait BlockNumberProvider {
2543 type BlockNumber: Codec
2545 + DecodeWithMemTracking
2546 + Clone
2547 + Ord
2548 + Eq
2549 + AtLeast32BitUnsigned
2550 + TypeInfo
2551 + Debug
2552 + MaxEncodedLen
2553 + Copy
2554 + EncodeLike
2555 + Default;
2556
2557 fn current_block_number() -> Self::BlockNumber;
2573
2574 #[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
2580 fn set_block_number(_block: Self::BlockNumber) {}
2581}
2582
2583impl BlockNumberProvider for () {
2584 type BlockNumber = u32;
2585 fn current_block_number() -> Self::BlockNumber {
2586 0
2587 }
2588}
2589
2590#[cfg(test)]
2591mod tests {
2592 use super::*;
2593 use crate::codec::{Decode, Encode, Input};
2594 #[cfg(feature = "bls-experimental")]
2595 use sp_core::ecdsa_bls381;
2596 use sp_core::{
2597 crypto::{Pair, UncheckedFrom},
2598 ecdsa, ed25519,
2599 proof_of_possession::ProofOfPossessionGenerator,
2600 sr25519,
2601 };
2602 use std::sync::Arc;
2603
2604 macro_rules! signature_verify_test {
2605 ($algorithm:ident) => {
2606 let msg = &b"test-message"[..];
2607 let wrong_msg = &b"test-msg"[..];
2608 let (pair, _) = $algorithm::Pair::generate();
2609
2610 let signature = pair.sign(&msg);
2611 assert!($algorithm::Pair::verify(&signature, msg, &pair.public()));
2612
2613 assert!(signature.verify(msg, &pair.public()));
2614 assert!(!signature.verify(wrong_msg, &pair.public()));
2615 };
2616 }
2617
2618 mod t {
2619 use sp_application_crypto::{app_crypto, sr25519};
2620 use sp_core::crypto::KeyTypeId;
2621 app_crypto!(sr25519, KeyTypeId(*b"test"));
2622 }
2623
2624 #[test]
2625 fn app_verify_works() {
2626 use super::AppVerify;
2627 use t::*;
2628
2629 let s = Signature::try_from(vec![0; 64]).unwrap();
2630 let _ = s.verify(&[0u8; 100][..], &Public::unchecked_from([0; 32]));
2631 }
2632
2633 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2634 struct U128Value(u128);
2635 impl super::TypeId for U128Value {
2636 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0x0d, 0xf0];
2637 }
2638 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2641 struct U32Value(u32);
2642 impl super::TypeId for U32Value {
2643 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
2644 }
2645 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2648 struct U16Value(u16);
2649 impl super::TypeId for U16Value {
2650 const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
2651 }
2652 type AccountId = u64;
2655
2656 #[test]
2657 fn into_account_truncating_should_work() {
2658 let r: AccountId = U32Value::into_account_truncating(&U32Value(0xdeadbeef));
2659 assert_eq!(r, 0x_deadbeef_cafef00d);
2660 }
2661
2662 #[test]
2663 fn try_into_account_should_work() {
2664 let r: AccountId = U32Value::try_into_account(&U32Value(0xdeadbeef)).unwrap();
2665 assert_eq!(r, 0x_deadbeef_cafef00d);
2666
2667 let maybe: Option<AccountId> = U128Value::try_into_account(&U128Value(u128::MAX));
2669 assert!(maybe.is_none());
2670 }
2671
2672 #[test]
2673 fn try_from_account_should_work() {
2674 let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
2675 assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
2676 }
2677
2678 #[test]
2679 fn into_account_truncating_with_fill_should_work() {
2680 let r: AccountId = U16Value::into_account_truncating(&U16Value(0xc0da));
2681 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2682 }
2683
2684 #[test]
2685 fn try_into_sub_account_should_work() {
2686 let r: AccountId = U16Value::try_into_account(&U16Value(0xc0da)).unwrap();
2687 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2688
2689 let maybe: Option<AccountId> = U16Value::try_into_sub_account(
2690 &U16Value(0xc0da),
2691 "a really large amount of additional encoded information which will certainly overflow the account id type ;)"
2692 );
2693
2694 assert!(maybe.is_none())
2695 }
2696
2697 #[test]
2698 fn try_from_account_with_fill_should_work() {
2699 let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
2700 assert_eq!(r.unwrap(), U16Value(0xc0da));
2701 }
2702
2703 #[test]
2704 fn bad_try_from_account_should_fail() {
2705 let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
2706 assert!(r.is_none());
2707 let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
2708 assert!(r.is_none());
2709 }
2710
2711 #[test]
2712 fn trailing_zero_should_work() {
2713 let mut t = super::TrailingZeroInput(&[1, 2, 3]);
2714 assert_eq!(t.remaining_len(), Ok(None));
2715 let mut buffer = [0u8; 2];
2716 assert_eq!(t.read(&mut buffer), Ok(()));
2717 assert_eq!(t.remaining_len(), Ok(None));
2718 assert_eq!(buffer, [1, 2]);
2719 assert_eq!(t.read(&mut buffer), Ok(()));
2720 assert_eq!(t.remaining_len(), Ok(None));
2721 assert_eq!(buffer, [3, 0]);
2722 assert_eq!(t.read(&mut buffer), Ok(()));
2723 assert_eq!(t.remaining_len(), Ok(None));
2724 assert_eq!(buffer, [0, 0]);
2725 }
2726
2727 #[test]
2728 fn ed25519_verify_works() {
2729 signature_verify_test!(ed25519);
2730 }
2731
2732 #[test]
2733 fn sr25519_verify_works() {
2734 signature_verify_test!(sr25519);
2735 }
2736
2737 #[test]
2738 fn ecdsa_verify_works() {
2739 signature_verify_test!(ecdsa);
2740 }
2741
2742 #[test]
2743 #[cfg(feature = "bls-experimental")]
2744 fn ecdsa_bls381_verify_works() {
2745 signature_verify_test!(ecdsa_bls381);
2746 }
2747
2748 pub struct Sr25519Key;
2749 impl crate::BoundToRuntimeAppPublic for Sr25519Key {
2750 type Public = sp_application_crypto::sr25519::AppPublic;
2751 }
2752
2753 pub struct Ed25519Key;
2754 impl crate::BoundToRuntimeAppPublic for Ed25519Key {
2755 type Public = sp_application_crypto::ed25519::AppPublic;
2756 }
2757
2758 pub struct EcdsaKey;
2759 impl crate::BoundToRuntimeAppPublic for EcdsaKey {
2760 type Public = sp_application_crypto::ecdsa::AppPublic;
2761 }
2762
2763 impl_opaque_keys! {
2764 pub struct SessionKeys {
2766 pub sr25519: Sr25519Key,
2767 pub ed25519: Ed25519Key,
2768 pub ecdsa: EcdsaKey,
2769 }
2770 }
2771
2772 #[test]
2773 fn opaque_keys_ownership_proof_works() {
2774 let mut sr25519 = sp_core::sr25519::Pair::generate().0;
2775 let mut ed25519 = sp_core::ed25519::Pair::generate().0;
2776 let mut ecdsa = sp_core::ecdsa::Pair::generate().0;
2777
2778 let session_keys = SessionKeys {
2779 sr25519: sr25519.public().into(),
2780 ed25519: ed25519.public().into(),
2781 ecdsa: ecdsa.public().into(),
2782 };
2783
2784 let owner = &b"owner"[..];
2785
2786 let sr25519_sig = sr25519.generate_proof_of_possession(&owner);
2787 let ed25519_sig = ed25519.generate_proof_of_possession(&owner);
2788 let ecdsa_sig = ecdsa.generate_proof_of_possession(&owner);
2789
2790 for invalidate in [None, Some(0), Some(1), Some(2)] {
2791 let proof = if let Some(invalidate) = invalidate {
2792 match invalidate {
2793 0 => (
2794 sr25519.generate_proof_of_possession(&b"invalid"[..]),
2795 &ed25519_sig,
2796 &ecdsa_sig,
2797 )
2798 .encode(),
2799 1 => (
2800 &sr25519_sig,
2801 ed25519.generate_proof_of_possession(&b"invalid"[..]),
2802 &ecdsa_sig,
2803 )
2804 .encode(),
2805 2 => (
2806 &sr25519_sig,
2807 &ed25519_sig,
2808 ecdsa.generate_proof_of_possession(&b"invalid"[..]),
2809 )
2810 .encode(),
2811 _ => unreachable!(),
2812 }
2813 } else {
2814 (&sr25519_sig, &ed25519_sig, &ecdsa_sig).encode()
2815 };
2816
2817 assert_eq!(session_keys.ownership_proof_is_valid(owner, &proof), invalidate.is_none());
2818 }
2819
2820 let proof = (&sr25519_sig, &ed25519_sig, &ecdsa_sig, "hello").encode();
2822 assert!(!session_keys.ownership_proof_is_valid(owner, &proof));
2823
2824 let mut ext = sp_io::TestExternalities::default();
2825 ext.register_extension(sp_keystore::KeystoreExt(Arc::new(
2826 sp_keystore::testing::MemoryKeystore::new(),
2827 )));
2828
2829 ext.execute_with(|| {
2830 let session_keys = SessionKeys::generate(&owner, None);
2831
2832 assert!(session_keys
2833 .keys
2834 .ownership_proof_is_valid(&owner, &session_keys.proof.encode()));
2835 });
2836 }
2837}