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 mod vers_tx_ext;
60pub use transaction_extension::{
61 DispatchTransaction, Implication, ImplicationParts, TransactionExtension,
62 TransactionExtensionMetadata, TxBaseImplication, ValidateResult,
63};
64pub use vers_tx_ext::{
65 DecodeWithVersion, DecodeWithVersionWithMemTracking, ExtensionVariant, InvalidVersion,
66 MultiVersion, Pipeline, PipelineAtVers, PipelineMetadataBuilder, PipelineVersion,
67};
68
69pub trait Lazy<T: ?Sized> {
71 fn get(&mut self) -> &T;
75}
76
77impl<'a> Lazy<[u8]> for &'a [u8] {
78 fn get(&mut self) -> &[u8] {
79 self
80 }
81}
82
83pub trait IdentifyAccount {
86 type AccountId;
88 fn into_account(self) -> Self::AccountId;
90}
91
92impl IdentifyAccount for sp_core::ed25519::Public {
93 type AccountId = Self;
94 fn into_account(self) -> Self {
95 self
96 }
97}
98
99impl IdentifyAccount for sp_core::sr25519::Public {
100 type AccountId = Self;
101 fn into_account(self) -> Self {
102 self
103 }
104}
105
106impl IdentifyAccount for sp_core::ecdsa::Public {
107 type AccountId = Self;
108 fn into_account(self) -> Self {
109 self
110 }
111}
112
113#[cfg(feature = "bls-experimental")]
114impl IdentifyAccount for sp_core::ecdsa_bls381::Public {
115 type AccountId = Self;
116 fn into_account(self) -> Self {
117 self
118 }
119}
120
121pub trait Verify {
123 type Signer: IdentifyAccount;
125 fn verify<L: Lazy<[u8]>>(
129 &self,
130 msg: L,
131 signer: &<Self::Signer as IdentifyAccount>::AccountId,
132 ) -> bool;
133}
134
135impl Verify for sp_core::ed25519::Signature {
136 type Signer = sp_core::ed25519::Public;
137
138 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ed25519::Public) -> bool {
139 sp_io::crypto::ed25519_verify(self, msg.get(), signer)
140 }
141}
142
143impl Verify for sp_core::sr25519::Signature {
144 type Signer = sp_core::sr25519::Public;
145
146 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::sr25519::Public) -> bool {
147 sp_io::crypto::sr25519_verify(self, msg.get(), signer)
148 }
149}
150
151impl Verify for sp_core::ecdsa::Signature {
152 type Signer = sp_core::ecdsa::Public;
153 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa::Public) -> bool {
154 match sp_io::crypto::secp256k1_ecdsa_recover_compressed(
155 self.as_ref(),
156 &sp_io::hashing::blake2_256(msg.get()),
157 ) {
158 Ok(pubkey) => signer.0 == pubkey,
159 _ => false,
160 }
161 }
162}
163
164#[cfg(feature = "bls-experimental")]
165impl Verify for sp_core::ecdsa_bls381::Signature {
166 type Signer = sp_core::ecdsa_bls381::Public;
167 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa_bls381::Public) -> bool {
168 <sp_core::ecdsa_bls381::Pair as sp_core::Pair>::verify(self, msg.get(), signer)
169 }
170}
171
172pub trait AppVerify {
174 type AccountId;
176 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &Self::AccountId) -> bool;
178}
179
180impl<
181 S: Verify<Signer = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic>
182 + From<T>,
183 T: sp_application_crypto::Wraps<Inner = S>
184 + sp_application_crypto::AppCrypto
185 + sp_application_crypto::AppSignature
186 + AsRef<S>
187 + AsMut<S>
188 + From<S>,
189 > AppVerify for T
190where
191 <S as Verify>::Signer: IdentifyAccount<AccountId = <S as Verify>::Signer>,
192 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
193 AccountId = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic,
194 >,
195{
196 type AccountId = <T as AppCrypto>::Public;
197 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppCrypto>::Public) -> bool {
198 use sp_application_crypto::IsWrappedBy;
199 let inner: &S = self.as_ref();
200 let inner_pubkey =
201 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(
202 signer,
203 );
204 Verify::verify(inner, msg, inner_pubkey)
205 }
206}
207
208#[derive(Encode, Decode, Debug)]
210pub struct BadOrigin;
211
212impl From<BadOrigin> for &'static str {
213 fn from(_: BadOrigin) -> &'static str {
214 "Bad origin"
215 }
216}
217
218#[derive(Encode, Decode, Debug)]
220pub struct LookupError;
221
222impl From<LookupError> for &'static str {
223 fn from(_: LookupError) -> &'static str {
224 "Can not lookup"
225 }
226}
227
228impl From<LookupError> for TransactionValidityError {
229 fn from(_: LookupError) -> Self {
230 UnknownTransaction::CannotLookup.into()
231 }
232}
233
234pub trait Lookup {
236 type Source;
238 type Target;
240 fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError>;
242}
243
244pub trait StaticLookup {
248 type Source: Codec + Clone + PartialEq + Debug + TypeInfo;
250 type Target;
252 fn lookup(s: Self::Source) -> Result<Self::Target, LookupError>;
254 fn unlookup(t: Self::Target) -> Self::Source;
256}
257
258#[derive(Clone, Copy, PartialEq, Eq)]
260pub struct IdentityLookup<T>(PhantomData<T>);
261impl<T> Default for IdentityLookup<T> {
262 fn default() -> Self {
263 Self(PhantomData::<T>::default())
264 }
265}
266
267impl<T: Codec + Clone + PartialEq + Debug + TypeInfo> StaticLookup for IdentityLookup<T> {
268 type Source = T;
269 type Target = T;
270 fn lookup(x: T) -> Result<T, LookupError> {
271 Ok(x)
272 }
273 fn unlookup(x: T) -> T {
274 x
275 }
276}
277
278impl<T> Lookup for IdentityLookup<T> {
279 type Source = T;
280 type Target = T;
281 fn lookup(&self, x: T) -> Result<T, LookupError> {
282 Ok(x)
283 }
284}
285
286pub struct AccountIdLookup<AccountId, AccountIndex>(PhantomData<(AccountId, AccountIndex)>);
288impl<AccountId, AccountIndex> StaticLookup for AccountIdLookup<AccountId, AccountIndex>
289where
290 AccountId: Codec + Clone + PartialEq + Debug,
291 AccountIndex: Codec + Clone + PartialEq + Debug,
292 crate::MultiAddress<AccountId, AccountIndex>: Codec + StaticTypeInfo,
293{
294 type Source = crate::MultiAddress<AccountId, AccountIndex>;
295 type Target = AccountId;
296 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
297 match x {
298 crate::MultiAddress::Id(i) => Ok(i),
299 _ => Err(LookupError),
300 }
301 }
302 fn unlookup(x: Self::Target) -> Self::Source {
303 crate::MultiAddress::Id(x)
304 }
305}
306
307impl<A, B> StaticLookup for (A, B)
309where
310 A: StaticLookup,
311 B: StaticLookup<Source = A::Source, Target = A::Target>,
312{
313 type Source = A::Source;
314 type Target = A::Target;
315
316 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
317 A::lookup(x.clone()).or_else(|_| B::lookup(x))
318 }
319 fn unlookup(x: Self::Target) -> Self::Source {
320 A::unlookup(x)
321 }
322}
323
324pub trait Morph<A> {
327 type Outcome;
329
330 fn morph(a: A) -> Self::Outcome;
332}
333
334impl<T> Morph<T> for Identity {
336 type Outcome = T;
337 fn morph(a: T) -> T {
338 a
339 }
340}
341
342pub trait TryMorph<A> {
345 type Outcome;
347
348 fn try_morph(a: A) -> Result<Self::Outcome, ()>;
350}
351
352impl<T> TryMorph<T> for Identity {
354 type Outcome = T;
355 fn try_morph(a: T) -> Result<T, ()> {
356 Ok(a)
357 }
358}
359
360pub struct MorphInto<T>(core::marker::PhantomData<T>);
362impl<T, A: Into<T>> Morph<A> for MorphInto<T> {
363 type Outcome = T;
364 fn morph(a: A) -> T {
365 a.into()
366 }
367}
368
369pub struct TryMorphInto<T>(core::marker::PhantomData<T>);
371impl<T, A: TryInto<T>> TryMorph<A> for TryMorphInto<T> {
372 type Outcome = T;
373 fn try_morph(a: A) -> Result<T, ()> {
374 a.try_into().map_err(|_| ())
375 }
376}
377
378pub struct TakeFirst;
380impl<T1> Morph<(T1,)> for TakeFirst {
381 type Outcome = T1;
382 fn morph(a: (T1,)) -> T1 {
383 a.0
384 }
385}
386impl<T1, T2> Morph<(T1, T2)> for TakeFirst {
387 type Outcome = T1;
388 fn morph(a: (T1, T2)) -> T1 {
389 a.0
390 }
391}
392impl<T1, T2, T3> Morph<(T1, T2, T3)> for TakeFirst {
393 type Outcome = T1;
394 fn morph(a: (T1, T2, T3)) -> T1 {
395 a.0
396 }
397}
398impl<T1, T2, T3, T4> Morph<(T1, T2, T3, T4)> for TakeFirst {
399 type Outcome = T1;
400 fn morph(a: (T1, T2, T3, T4)) -> T1 {
401 a.0
402 }
403}
404
405#[macro_export]
441macro_rules! morph_types {
442 (
443 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ()
444 ) => {
445 $( #[doc = $doc] )* $vq struct $name;
446 };
447 (
448 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ( $( $bound_id:ident ),+ )
449 ) => {
450 $( #[doc = $doc] )*
451 $vq struct $name < $($bound_id,)* > ( $crate::traits::PhantomData< ( $($bound_id,)* ) > ) ;
452 };
453 (
454 @IMPL $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
455 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
456 ) => {
457 impl<$($bounds)*> $crate::traits::Morph<$var_type> for $name $( $where )? {
458 type Outcome = $outcome;
459 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
460 }
461 };
462 (
463 @IMPL_TRY $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
464 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
465 ) => {
466 impl<$($bounds)*> $crate::traits::TryMorph<$var_type> for $name $( $where )? {
467 type Outcome = $outcome;
468 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
469 }
470 };
471 (
472 @IMPL $name:ty : () ( $( $where:tt )* )
473 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
474 ) => {
475 impl $crate::traits::Morph<$var_type> for $name $( $where )? {
476 type Outcome = $outcome;
477 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
478 }
479 };
480 (
481 @IMPL_TRY $name:ty : () ( $( $where:tt )* )
482 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
483 ) => {
484 impl $crate::traits::TryMorph<$var_type> for $name $( $where )? {
485 type Outcome = $outcome;
486 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
487 }
488 };
489 (
490 @IMPL_BOTH $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
491 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
492 ) => {
493 morph_types! {
494 @IMPL $name : ($($bounds)*) ($($where)*)
495 = |$var: $var_type| -> $outcome { $( $ex )* }
496 }
497 morph_types! {
498 @IMPL_TRY $name : ($($bounds)*) ($($where)*)
499 = |$var: $var_type| -> $outcome { Ok({$( $ex )*}) }
500 }
501 };
502
503 (
504 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
505 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
506 $(: $type:tt)?
507 = |_| -> $outcome:ty { $( $ex:expr )* };
508 $( $rest:tt )*
509 ) => {
510 morph_types! {
511 $( #[doc = $doc] )* $vq type $name
512 $( < $( $bound_id $( : $bound_head $( | $bound_tail )* )? ),+ > )?
513 EXTRA_GENERIC(X)
514 $(: $type)?
515 = |_x: X| -> $outcome { $( $ex )* };
516 $( $rest )*
517 }
518 };
519 (
520 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
521 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
522 $( EXTRA_GENERIC ($extra:ident) )?
523 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
524 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
525 $( $rest:tt )*
526 ) => {
527 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
528 morph_types! {
529 @IMPL_BOTH $name $( < $( $bound_id ),* > )? :
530 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
531 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
532 = |$var: $var_type| -> $outcome { $( $ex )* }
533 }
534 morph_types!{ $($rest)* }
535 };
536 (
537 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
538 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
539 $( EXTRA_GENERIC ($extra:ident) )?
540 : Morph
541 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
542 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
543 $( $rest:tt )*
544 ) => {
545 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
546 morph_types! {
547 @IMPL $name $( < $( $bound_id ),* > )? :
548 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
549 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
550 = |$var: $var_type| -> $outcome { $( $ex )* }
551 }
552 morph_types!{ $($rest)* }
553 };
554 (
555 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
556 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
557 $( EXTRA_GENERIC ($extra:ident) )?
558 : TryMorph
559 = |$var:ident: $var_type:ty| -> Result<$outcome:ty, ()> { $( $ex:expr )* }
560 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
561 $( $rest:tt )*
562 ) => {
563 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
564 morph_types! {
565 @IMPL_TRY $name $( < $( $bound_id ),* > )? :
566 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
567 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
568 = |$var: $var_type| -> $outcome { $( $ex )* }
569 }
570 morph_types!{ $($rest)* }
571 };
572 () => {}
573}
574
575morph_types! {
576 pub type Replace<V: TypedGet> = |_| -> V::Type { V::get() };
578
579 pub type ReplaceWithDefault<V: Default> = |_| -> V { Default::default() };
581
582 pub type ReduceBy<N: TypedGet> = |r: N::Type| -> N::Type {
584 r.checked_sub(&N::get()).unwrap_or(Zero::zero())
585 } where N::Type: CheckedSub | Zero;
586
587 pub type CheckedReduceBy<N: TypedGet>: TryMorph = |r: N::Type| -> Result<N::Type, ()> {
590 r.checked_sub(&N::get()).ok_or(())
591 } where N::Type: CheckedSub;
592
593 pub type MorphWithUpperLimit<L: TypedGet, M>: TryMorph = |r: L::Type| -> Result<L::Type, ()> {
595 M::try_morph(r).map(|m| m.min(L::get()))
596 } where L::Type: Ord, M: TryMorph<L::Type, Outcome = L::Type>;
597}
598
599pub trait Convert<A, B> {
601 fn convert(a: A) -> B;
603}
604
605impl<A, B: Default> Convert<A, B> for () {
606 fn convert(_: A) -> B {
607 Default::default()
608 }
609}
610
611pub trait ConvertBack<A, B>: Convert<A, B> {
615 fn convert_back(b: B) -> A;
617}
618
619pub trait MaybeConvert<A, B> {
621 fn maybe_convert(a: A) -> Option<B>;
623}
624
625#[impl_trait_for_tuples::impl_for_tuples(30)]
626impl<A: Clone, B> MaybeConvert<A, B> for Tuple {
627 fn maybe_convert(a: A) -> Option<B> {
628 for_tuples!( #(
629 match Tuple::maybe_convert(a.clone()) {
630 Some(b) => return Some(b),
631 None => {},
632 }
633 )* );
634 None
635 }
636}
637
638pub trait MaybeConvertBack<A, B>: MaybeConvert<A, B> {
641 fn maybe_convert_back(b: B) -> Option<A>;
643}
644
645#[impl_trait_for_tuples::impl_for_tuples(30)]
646impl<A: Clone, B: Clone> MaybeConvertBack<A, B> for Tuple {
647 fn maybe_convert_back(b: B) -> Option<A> {
648 for_tuples!( #(
649 match Tuple::maybe_convert_back(b.clone()) {
650 Some(a) => return Some(a),
651 None => {},
652 }
653 )* );
654 None
655 }
656}
657
658pub trait TryConvert<A, B> {
661 fn try_convert(a: A) -> Result<B, A>;
663}
664
665#[impl_trait_for_tuples::impl_for_tuples(30)]
666impl<A, B> TryConvert<A, B> for Tuple {
667 fn try_convert(a: A) -> Result<B, A> {
668 for_tuples!( #(
669 let a = match Tuple::try_convert(a) {
670 Ok(b) => return Ok(b),
671 Err(a) => a,
672 };
673 )* );
674 Err(a)
675 }
676}
677
678pub trait TryConvertBack<A, B>: TryConvert<A, B> {
681 fn try_convert_back(b: B) -> Result<A, B>;
684}
685
686#[impl_trait_for_tuples::impl_for_tuples(30)]
687impl<A, B> TryConvertBack<A, B> for Tuple {
688 fn try_convert_back(b: B) -> Result<A, B> {
689 for_tuples!( #(
690 let b = match Tuple::try_convert_back(b) {
691 Ok(a) => return Ok(a),
692 Err(b) => b,
693 };
694 )* );
695 Err(b)
696 }
697}
698
699pub trait MaybeEquivalence<A, B> {
701 fn convert(a: &A) -> Option<B>;
703 fn convert_back(b: &B) -> Option<A>;
705}
706
707#[impl_trait_for_tuples::impl_for_tuples(30)]
708impl<A, B> MaybeEquivalence<A, B> for Tuple {
709 fn convert(a: &A) -> Option<B> {
710 for_tuples!( #(
711 match Tuple::convert(a) {
712 Some(b) => return Some(b),
713 None => {},
714 }
715 )* );
716 None
717 }
718 fn convert_back(b: &B) -> Option<A> {
719 for_tuples!( #(
720 match Tuple::convert_back(b) {
721 Some(a) => return Some(a),
722 None => {},
723 }
724 )* );
725 None
726 }
727}
728
729pub struct ConvertToValue<T>(core::marker::PhantomData<T>);
732impl<X, Y, T: Get<Y>> Convert<X, Y> for ConvertToValue<T> {
733 fn convert(_: X) -> Y {
734 T::get()
735 }
736}
737impl<X, Y, T: Get<Y>> MaybeConvert<X, Y> for ConvertToValue<T> {
738 fn maybe_convert(_: X) -> Option<Y> {
739 Some(T::get())
740 }
741}
742impl<X, Y, T: Get<Y>> MaybeConvertBack<X, Y> for ConvertToValue<T> {
743 fn maybe_convert_back(_: Y) -> Option<X> {
744 None
745 }
746}
747impl<X, Y, T: Get<Y>> TryConvert<X, Y> for ConvertToValue<T> {
748 fn try_convert(_: X) -> Result<Y, X> {
749 Ok(T::get())
750 }
751}
752impl<X, Y, T: Get<Y>> TryConvertBack<X, Y> for ConvertToValue<T> {
753 fn try_convert_back(y: Y) -> Result<X, Y> {
754 Err(y)
755 }
756}
757impl<X, Y, T: Get<Y>> MaybeEquivalence<X, Y> for ConvertToValue<T> {
758 fn convert(_: &X) -> Option<Y> {
759 Some(T::get())
760 }
761 fn convert_back(_: &Y) -> Option<X> {
762 None
763 }
764}
765
766pub struct Identity;
768impl<T> Convert<T, T> for Identity {
769 fn convert(a: T) -> T {
770 a
771 }
772}
773impl<T> ConvertBack<T, T> for Identity {
774 fn convert_back(a: T) -> T {
775 a
776 }
777}
778impl<T> MaybeConvert<T, T> for Identity {
779 fn maybe_convert(a: T) -> Option<T> {
780 Some(a)
781 }
782}
783impl<T> MaybeConvertBack<T, T> for Identity {
784 fn maybe_convert_back(a: T) -> Option<T> {
785 Some(a)
786 }
787}
788impl<T> TryConvert<T, T> for Identity {
789 fn try_convert(a: T) -> Result<T, T> {
790 Ok(a)
791 }
792}
793impl<T> TryConvertBack<T, T> for Identity {
794 fn try_convert_back(a: T) -> Result<T, T> {
795 Ok(a)
796 }
797}
798impl<T: Clone> MaybeEquivalence<T, T> for Identity {
799 fn convert(a: &T) -> Option<T> {
800 Some(a.clone())
801 }
802 fn convert_back(a: &T) -> Option<T> {
803 Some(a.clone())
804 }
805}
806
807pub struct ConvertInto;
809impl<A: Into<B>, B> Convert<A, B> for ConvertInto {
810 fn convert(a: A) -> B {
811 a.into()
812 }
813}
814impl<A: Into<B>, B> MaybeConvert<A, B> for ConvertInto {
815 fn maybe_convert(a: A) -> Option<B> {
816 Some(a.into())
817 }
818}
819impl<A: Into<B>, B: Into<A>> MaybeConvertBack<A, B> for ConvertInto {
820 fn maybe_convert_back(b: B) -> Option<A> {
821 Some(b.into())
822 }
823}
824impl<A: Into<B>, B> TryConvert<A, B> for ConvertInto {
825 fn try_convert(a: A) -> Result<B, A> {
826 Ok(a.into())
827 }
828}
829impl<A: Into<B>, B: Into<A>> TryConvertBack<A, B> for ConvertInto {
830 fn try_convert_back(b: B) -> Result<A, B> {
831 Ok(b.into())
832 }
833}
834impl<A: Clone + Into<B>, B: Clone + Into<A>> MaybeEquivalence<A, B> for ConvertInto {
835 fn convert(a: &A) -> Option<B> {
836 Some(a.clone().into())
837 }
838 fn convert_back(b: &B) -> Option<A> {
839 Some(b.clone().into())
840 }
841}
842
843pub struct TryConvertInto;
845impl<A: Clone + TryInto<B>, B> MaybeConvert<A, B> for TryConvertInto {
846 fn maybe_convert(a: A) -> Option<B> {
847 a.clone().try_into().ok()
848 }
849}
850impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeConvertBack<A, B> for TryConvertInto {
851 fn maybe_convert_back(b: B) -> Option<A> {
852 b.clone().try_into().ok()
853 }
854}
855impl<A: Clone + TryInto<B>, B> TryConvert<A, B> for TryConvertInto {
856 fn try_convert(a: A) -> Result<B, A> {
857 a.clone().try_into().map_err(|_| a)
858 }
859}
860impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> TryConvertBack<A, B> for TryConvertInto {
861 fn try_convert_back(b: B) -> Result<A, B> {
862 b.clone().try_into().map_err(|_| b)
863 }
864}
865impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeEquivalence<A, B> for TryConvertInto {
866 fn convert(a: &A) -> Option<B> {
867 a.clone().try_into().ok()
868 }
869 fn convert_back(b: &B) -> Option<A> {
870 b.clone().try_into().ok()
871 }
872}
873
874pub trait CheckedConversion {
878 fn checked_from<T>(t: T) -> Option<Self>
884 where
885 Self: TryFrom<T>,
886 {
887 <Self as TryFrom<T>>::try_from(t).ok()
888 }
889 fn checked_into<T>(self) -> Option<T>
895 where
896 Self: TryInto<T>,
897 {
898 <Self as TryInto<T>>::try_into(self).ok()
899 }
900}
901impl<T: Sized> CheckedConversion for T {}
902
903pub trait Scale<Other> {
906 type Output;
908
909 fn mul(self, other: Other) -> Self::Output;
911
912 fn div(self, other: Other) -> Self::Output;
914
915 fn rem(self, other: Other) -> Self::Output;
917}
918macro_rules! impl_scale {
919 ($self:ty, $other:ty) => {
920 impl Scale<$other> for $self {
921 type Output = Self;
922 fn mul(self, other: $other) -> Self::Output {
923 self * (other as Self)
924 }
925 fn div(self, other: $other) -> Self::Output {
926 self / (other as Self)
927 }
928 fn rem(self, other: $other) -> Self::Output {
929 self % (other as Self)
930 }
931 }
932 };
933}
934impl_scale!(u128, u128);
935impl_scale!(u128, u64);
936impl_scale!(u128, u32);
937impl_scale!(u128, u16);
938impl_scale!(u128, u8);
939impl_scale!(u64, u64);
940impl_scale!(u64, u32);
941impl_scale!(u64, u16);
942impl_scale!(u64, u8);
943impl_scale!(u32, u32);
944impl_scale!(u32, u16);
945impl_scale!(u32, u8);
946impl_scale!(u16, u16);
947impl_scale!(u16, u8);
948impl_scale!(u8, u8);
949
950pub trait Clear {
953 fn is_clear(&self) -> bool;
955
956 fn clear() -> Self;
958}
959
960impl<T: Default + Eq + PartialEq> Clear for T {
961 fn is_clear(&self) -> bool {
962 *self == Self::clear()
963 }
964 fn clear() -> Self {
965 Default::default()
966 }
967}
968
969pub trait SimpleBitOps:
971 Sized
972 + Clear
973 + core::ops::BitOr<Self, Output = Self>
974 + core::ops::BitXor<Self, Output = Self>
975 + core::ops::BitAnd<Self, Output = Self>
976{
977}
978impl<
979 T: Sized
980 + Clear
981 + core::ops::BitOr<Self, Output = Self>
982 + core::ops::BitXor<Self, Output = Self>
983 + core::ops::BitAnd<Self, Output = Self>,
984 > SimpleBitOps for T
985{
986}
987
988pub trait Hash:
992 'static
993 + MaybeSerializeDeserialize
994 + Debug
995 + Clone
996 + Eq
997 + PartialEq
998 + Hasher<Out = <Self as Hash>::Output>
999{
1000 type Output: HashOutput;
1002
1003 fn hash(s: &[u8]) -> Self::Output {
1005 <Self as Hasher>::hash(s)
1006 }
1007
1008 fn hash_of<S: Encode>(s: &S) -> Self::Output {
1010 Encode::using_encoded(s, <Self as Hasher>::hash)
1011 }
1012
1013 fn ordered_trie_root(input: Vec<Vec<u8>>, state_version: StateVersion) -> Self::Output;
1015
1016 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, state_version: StateVersion) -> Self::Output;
1018}
1019
1020pub trait HashOutput:
1022 Member
1023 + MaybeSerializeDeserialize
1024 + MaybeDisplay
1025 + MaybeFromStr
1026 + Debug
1027 + core::hash::Hash
1028 + AsRef<[u8]>
1029 + AsMut<[u8]>
1030 + Copy
1031 + Ord
1032 + Default
1033 + Encode
1034 + Decode
1035 + DecodeWithMemTracking
1036 + EncodeLike
1037 + MaxEncodedLen
1038 + TypeInfo
1039{
1040}
1041
1042impl<T> HashOutput for T where
1043 T: Member
1044 + MaybeSerializeDeserialize
1045 + MaybeDisplay
1046 + MaybeFromStr
1047 + Debug
1048 + core::hash::Hash
1049 + AsRef<[u8]>
1050 + AsMut<[u8]>
1051 + Copy
1052 + Ord
1053 + Default
1054 + Encode
1055 + Decode
1056 + DecodeWithMemTracking
1057 + EncodeLike
1058 + MaxEncodedLen
1059 + TypeInfo
1060{
1061}
1062
1063#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1065#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1066pub struct BlakeTwo256;
1067
1068impl Hasher for BlakeTwo256 {
1069 type Out = sp_core::H256;
1070 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1071 const LENGTH: usize = 32;
1072
1073 fn hash(s: &[u8]) -> Self::Out {
1074 sp_io::hashing::blake2_256(s).into()
1075 }
1076}
1077
1078impl Hash for BlakeTwo256 {
1079 type Output = sp_core::H256;
1080
1081 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1082 sp_io::trie::blake2_256_ordered_root(input, version)
1083 }
1084
1085 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1086 sp_io::trie::blake2_256_root(input, version)
1087 }
1088}
1089
1090#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1092#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1093pub struct Keccak256;
1094
1095impl Hasher for Keccak256 {
1096 type Out = sp_core::H256;
1097 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1098 const LENGTH: usize = 32;
1099
1100 fn hash(s: &[u8]) -> Self::Out {
1101 sp_io::hashing::keccak_256(s).into()
1102 }
1103}
1104
1105impl Hash for Keccak256 {
1106 type Output = sp_core::H256;
1107
1108 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1109 sp_io::trie::keccak_256_ordered_root(input, version)
1110 }
1111
1112 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1113 sp_io::trie::keccak_256_root(input, version)
1114 }
1115}
1116
1117pub trait CheckEqual {
1119 fn check_equal(&self, other: &Self);
1121}
1122
1123impl CheckEqual for sp_core::H256 {
1124 #[cfg(feature = "std")]
1125 fn check_equal(&self, other: &Self) {
1126 use sp_core::hexdisplay::HexDisplay;
1127 if self != other {
1128 println!(
1129 "Hash: given={}, expected={}",
1130 HexDisplay::from(self.as_fixed_bytes()),
1131 HexDisplay::from(other.as_fixed_bytes()),
1132 );
1133 }
1134 }
1135
1136 #[cfg(not(feature = "std"))]
1137 fn check_equal(&self, other: &Self) {
1138 if self != other {
1139 "Hash not equal".print();
1140 self.as_bytes().print();
1141 other.as_bytes().print();
1142 }
1143 }
1144}
1145
1146impl CheckEqual for super::generic::DigestItem {
1147 #[cfg(feature = "std")]
1148 fn check_equal(&self, other: &Self) {
1149 if self != other {
1150 println!("DigestItem: given={:?}, expected={:?}", self, other);
1151 }
1152 }
1153
1154 #[cfg(not(feature = "std"))]
1155 fn check_equal(&self, other: &Self) {
1156 if self != other {
1157 "DigestItem not equal".print();
1158 (&Encode::encode(self)[..]).print();
1159 (&Encode::encode(other)[..]).print();
1160 }
1161 }
1162}
1163
1164sp_core::impl_maybe_marker!(
1165 trait MaybeDisplay: Display;
1167
1168 trait MaybeFromStr: FromStr;
1170
1171 trait MaybeHash: core::hash::Hash;
1173);
1174
1175sp_core::impl_maybe_marker_std_or_serde!(
1176 trait MaybeSerialize: Serialize;
1178
1179 trait MaybeSerializeDeserialize: DeserializeOwned, Serialize;
1181);
1182
1183pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {}
1185impl<T: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static> Member for T {}
1186
1187pub trait IsMember<MemberId> {
1189 fn is_member(member_id: &MemberId) -> bool;
1191}
1192
1193pub trait BlockNumber:
1195 Member
1196 + MaybeSerializeDeserialize
1197 + MaybeFromStr
1198 + Debug
1199 + core::hash::Hash
1200 + Copy
1201 + MaybeDisplay
1202 + AtLeast32BitUnsigned
1203 + Into<U256>
1204 + TryFrom<U256>
1205 + Default
1206 + TypeInfo
1207 + MaxEncodedLen
1208 + FullCodec
1209 + DecodeWithMemTracking
1210 + HasCompact<Type: DecodeWithMemTracking>
1211{
1212}
1213
1214impl<
1215 T: Member
1216 + MaybeSerializeDeserialize
1217 + MaybeFromStr
1218 + Debug
1219 + core::hash::Hash
1220 + Copy
1221 + MaybeDisplay
1222 + AtLeast32BitUnsigned
1223 + Into<U256>
1224 + TryFrom<U256>
1225 + Default
1226 + TypeInfo
1227 + MaxEncodedLen
1228 + FullCodec
1229 + DecodeWithMemTracking
1230 + HasCompact<Type: DecodeWithMemTracking>,
1231 > BlockNumber for T
1232{
1233}
1234
1235pub trait Header:
1241 Clone
1242 + Send
1243 + Sync
1244 + Codec
1245 + DecodeWithMemTracking
1246 + Eq
1247 + MaybeSerialize
1248 + Debug
1249 + TypeInfo
1250 + 'static
1251{
1252 type Number: BlockNumber;
1254 type Hash: HashOutput;
1256 type Hashing: Hash<Output = Self::Hash>;
1258
1259 fn new(
1261 number: Self::Number,
1262 extrinsics_root: Self::Hash,
1263 state_root: Self::Hash,
1264 parent_hash: Self::Hash,
1265 digest: Digest,
1266 ) -> Self;
1267
1268 fn number(&self) -> &Self::Number;
1270 fn set_number(&mut self, number: Self::Number);
1272
1273 fn extrinsics_root(&self) -> &Self::Hash;
1275 fn set_extrinsics_root(&mut self, root: Self::Hash);
1277
1278 fn state_root(&self) -> &Self::Hash;
1280 fn set_state_root(&mut self, root: Self::Hash);
1282
1283 fn parent_hash(&self) -> &Self::Hash;
1285 fn set_parent_hash(&mut self, hash: Self::Hash);
1287
1288 fn digest(&self) -> &Digest;
1290 fn digest_mut(&mut self) -> &mut Digest;
1292
1293 fn hash(&self) -> Self::Hash {
1295 <Self::Hashing as Hash>::hash_of(self)
1296 }
1297}
1298
1299#[doc(hidden)]
1319pub trait HeaderProvider {
1320 type HeaderT: Header;
1322}
1323
1324pub trait LazyExtrinsic: Sized {
1326 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error>;
1334}
1335
1336pub trait LazyBlock: Debug + Encode + Decode + Sized {
1338 type Extrinsic: LazyExtrinsic;
1340 type Header: Header;
1342
1343 fn header(&self) -> &Self::Header;
1345
1346 fn header_mut(&mut self) -> &mut Self::Header;
1348
1349 fn extrinsics(&self) -> impl Iterator<Item = Result<Self::Extrinsic, codec::Error>>;
1353}
1354
1355pub trait Block:
1360 HeaderProvider<HeaderT = Self::Header>
1361 + Into<Self::LazyBlock>
1362 + EncodeLike<Self::LazyBlock>
1363 + Clone
1364 + Send
1365 + Sync
1366 + Codec
1367 + DecodeWithMemTracking
1368 + Eq
1369 + MaybeSerialize
1370 + Debug
1371 + 'static
1372{
1373 type Extrinsic: Member + Codec + ExtrinsicLike + MaybeSerialize + Into<OpaqueExtrinsic>;
1375 type Header: Header<Hash = Self::Hash> + MaybeSerializeDeserialize;
1377 type Hash: HashOutput;
1379
1380 type LazyBlock: LazyBlock<Extrinsic = Self::Extrinsic, Header = Self::Header> + EncodeLike<Self>;
1383
1384 fn header(&self) -> &Self::Header;
1386 fn extrinsics(&self) -> &[Self::Extrinsic];
1388 fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>);
1390 fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self;
1392 fn hash(&self) -> Self::Hash {
1394 <<Self::Header as Header>::Hashing as Hash>::hash_of(self.header())
1395 }
1396}
1397
1398#[deprecated = "Use `ExtrinsicLike` along with the `CreateTransaction` trait family instead"]
1400pub trait Extrinsic: Sized {
1401 type Call: TypeInfo;
1403
1404 type SignaturePayload: SignaturePayload;
1410
1411 fn is_signed(&self) -> Option<bool> {
1414 None
1415 }
1416
1417 fn is_bare(&self) -> bool {
1419 !self.is_signed().unwrap_or(true)
1420 }
1421
1422 fn new(_call: Self::Call, _signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
1425 None
1426 }
1427}
1428
1429pub trait ExtrinsicLike: Sized {
1431 #[deprecated = "Use and implement `!is_bare()` instead"]
1434 fn is_signed(&self) -> Option<bool> {
1435 None
1436 }
1437
1438 fn is_bare(&self) -> bool {
1440 #[allow(deprecated)]
1441 !self.is_signed().unwrap_or(true)
1442 }
1443}
1444
1445#[allow(deprecated)]
1446impl<T> ExtrinsicLike for T
1447where
1448 T: Extrinsic,
1449{
1450 fn is_signed(&self) -> Option<bool> {
1451 #[allow(deprecated)]
1452 <Self as Extrinsic>::is_signed(&self)
1453 }
1454
1455 fn is_bare(&self) -> bool {
1456 <Self as Extrinsic>::is_bare(&self)
1457 }
1458}
1459
1460pub trait ExtrinsicCall: ExtrinsicLike {
1462 type Call;
1464
1465 fn call(&self) -> &Self::Call;
1467
1468 fn into_call(self) -> Self::Call;
1470}
1471
1472pub trait SignaturePayload {
1475 type SignatureAddress: TypeInfo;
1479
1480 type Signature: TypeInfo;
1484
1485 type SignatureExtra: TypeInfo;
1489}
1490
1491impl SignaturePayload for () {
1492 type SignatureAddress = ();
1493 type Signature = ();
1494 type SignatureExtra = ();
1495}
1496
1497pub trait ExtrinsicMetadata {
1499 const VERSIONS: &'static [u8];
1503
1504 type TransactionExtensionPipelines;
1511}
1512
1513pub type HashingFor<B> = <<B as Block>::Header as Header>::Hashing;
1515pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
1517pub trait Checkable<Context>: Sized {
1524 type Checked;
1526
1527 fn check(self, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
1529
1530 #[cfg(feature = "try-runtime")]
1539 fn unchecked_into_checked_i_know_what_i_am_doing(
1540 self,
1541 c: &Context,
1542 ) -> Result<Self::Checked, TransactionValidityError>;
1543}
1544
1545pub trait BlindCheckable: Sized {
1550 type Checked;
1552
1553 fn check(self) -> Result<Self::Checked, TransactionValidityError>;
1555}
1556
1557impl<T: BlindCheckable, Context> Checkable<Context> for T {
1559 type Checked = <Self as BlindCheckable>::Checked;
1560
1561 fn check(self, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
1562 BlindCheckable::check(self)
1563 }
1564
1565 #[cfg(feature = "try-runtime")]
1566 fn unchecked_into_checked_i_know_what_i_am_doing(
1567 self,
1568 _: &Context,
1569 ) -> Result<Self::Checked, TransactionValidityError> {
1570 unreachable!();
1571 }
1572}
1573
1574pub trait RefundWeight {
1576 fn refund(&mut self, weight: sp_weights::Weight);
1578}
1579
1580pub trait ExtensionPostDispatchWeightHandler<DispatchInfo>: RefundWeight {
1583 fn set_extension_weight(&mut self, info: &DispatchInfo);
1585}
1586
1587impl RefundWeight for () {
1588 fn refund(&mut self, _weight: sp_weights::Weight) {}
1589}
1590
1591impl ExtensionPostDispatchWeightHandler<()> for () {
1592 fn set_extension_weight(&mut self, _info: &()) {}
1593}
1594
1595pub trait Dispatchable {
1598 type RuntimeOrigin: Debug;
1602 type Config;
1604 type Info;
1608 type PostInfo: Eq
1611 + PartialEq
1612 + Clone
1613 + Copy
1614 + Encode
1615 + Decode
1616 + Printable
1617 + ExtensionPostDispatchWeightHandler<Self::Info>;
1618 fn dispatch(self, origin: Self::RuntimeOrigin)
1620 -> crate::DispatchResultWithInfo<Self::PostInfo>;
1621}
1622
1623pub type DispatchOriginOf<T> = <T as Dispatchable>::RuntimeOrigin;
1625pub type DispatchInfoOf<T> = <T as Dispatchable>::Info;
1627pub type PostDispatchInfoOf<T> = <T as Dispatchable>::PostInfo;
1629
1630impl Dispatchable for () {
1631 type RuntimeOrigin = ();
1632 type Config = ();
1633 type Info = ();
1634 type PostInfo = ();
1635 fn dispatch(
1636 self,
1637 _origin: Self::RuntimeOrigin,
1638 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1639 panic!("This implementation should not be used for actual dispatch.");
1640 }
1641}
1642
1643#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
1645pub struct FakeDispatchable<Inner>(pub Inner);
1646impl<Inner> From<Inner> for FakeDispatchable<Inner> {
1647 fn from(inner: Inner) -> Self {
1648 Self(inner)
1649 }
1650}
1651impl<Inner> FakeDispatchable<Inner> {
1652 pub fn deconstruct(self) -> Inner {
1654 self.0
1655 }
1656}
1657impl<Inner> AsRef<Inner> for FakeDispatchable<Inner> {
1658 fn as_ref(&self) -> &Inner {
1659 &self.0
1660 }
1661}
1662
1663impl<Inner> Dispatchable for FakeDispatchable<Inner> {
1664 type RuntimeOrigin = ();
1665 type Config = ();
1666 type Info = ();
1667 type PostInfo = ();
1668 fn dispatch(
1669 self,
1670 _origin: Self::RuntimeOrigin,
1671 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1672 panic!("This implementation should not be used for actual dispatch.");
1673 }
1674}
1675
1676pub trait AsSystemOriginSigner<AccountId> {
1678 fn as_system_origin_signer(&self) -> Option<&AccountId>;
1681}
1682
1683pub trait AsTransactionAuthorizedOrigin {
1697 fn is_transaction_authorized(&self) -> bool;
1707}
1708
1709#[deprecated = "Use `TransactionExtension` instead."]
1712pub trait SignedExtension:
1713 Codec + DecodeWithMemTracking + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
1714{
1715 const IDENTIFIER: &'static str;
1720
1721 type AccountId;
1723
1724 type Call: Dispatchable;
1726
1727 type AdditionalSigned: Codec + TypeInfo;
1730
1731 type Pre;
1733
1734 fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError>;
1737
1738 fn validate(
1748 &self,
1749 _who: &Self::AccountId,
1750 _call: &Self::Call,
1751 _info: &DispatchInfoOf<Self::Call>,
1752 _len: usize,
1753 ) -> TransactionValidity {
1754 Ok(ValidTransaction::default())
1755 }
1756
1757 fn pre_dispatch(
1761 self,
1762 who: &Self::AccountId,
1763 call: &Self::Call,
1764 info: &DispatchInfoOf<Self::Call>,
1765 len: usize,
1766 ) -> Result<Self::Pre, TransactionValidityError>;
1767
1768 fn post_dispatch(
1785 _pre: Option<Self::Pre>,
1786 _info: &DispatchInfoOf<Self::Call>,
1787 _post_info: &PostDispatchInfoOf<Self::Call>,
1788 _len: usize,
1789 _result: &DispatchResult,
1790 ) -> Result<(), TransactionValidityError> {
1791 Ok(())
1792 }
1793
1794 fn metadata() -> Vec<TransactionExtensionMetadata> {
1803 alloc::vec![TransactionExtensionMetadata {
1804 identifier: Self::IDENTIFIER,
1805 ty: scale_info::meta_type::<Self>(),
1806 implicit: scale_info::meta_type::<Self::AdditionalSigned>()
1807 }]
1808 }
1809
1810 fn validate_unsigned(
1817 _call: &Self::Call,
1818 _info: &DispatchInfoOf<Self::Call>,
1819 _len: usize,
1820 ) -> TransactionValidity {
1821 Ok(ValidTransaction::default())
1822 }
1823
1824 fn pre_dispatch_unsigned(
1833 call: &Self::Call,
1834 info: &DispatchInfoOf<Self::Call>,
1835 len: usize,
1836 ) -> Result<(), TransactionValidityError> {
1837 Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into)
1838 }
1839}
1840
1841pub trait Applyable: Sized + Send + Sync {
1857 type Call: Dispatchable;
1859
1860 #[allow(deprecated)]
1865 fn validate<V: ValidateUnsigned<Call = Self::Call>>(
1866 &self,
1867 source: TransactionSource,
1868 info: &DispatchInfoOf<Self::Call>,
1869 len: usize,
1870 ) -> TransactionValidity;
1871
1872 #[allow(deprecated)]
1878 fn apply<V: ValidateUnsigned<Call = Self::Call>>(
1879 self,
1880 info: &DispatchInfoOf<Self::Call>,
1881 len: usize,
1882 ) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>>;
1883}
1884
1885pub trait GetRuntimeBlockType {
1887 type RuntimeBlock: self::Block;
1889}
1890
1891pub trait GetNodeBlockType {
1893 type NodeBlock: self::Block;
1895}
1896
1897#[deprecated(
1912 note = "`ValidateUnsigned` will be removed after April 2027. Use `#[pallet::authorize]` with `frame_system::AuthorizeCall` instead. See https://github.com/paritytech/polkadot-sdk/issues/2415"
1913)]
1914pub trait ValidateUnsigned {
1915 type Call;
1917
1918 fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
1931 Self::validate_unsigned(TransactionSource::InBlock, call)
1932 .map(|_| ())
1933 .map_err(Into::into)
1934 }
1935
1936 fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity;
1949}
1950
1951pub trait OpaqueKeys: Clone {
1954 type KeyTypeIdProviders;
1958
1959 fn key_ids() -> &'static [KeyTypeId];
1961
1962 fn get_raw(&self, i: KeyTypeId) -> &[u8];
1964
1965 fn get<T: Decode>(&self, i: KeyTypeId) -> Option<T> {
1967 T::decode(&mut self.get_raw(i)).ok()
1968 }
1969
1970 #[must_use]
1972 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool;
1973}
1974
1975pub struct AppendZerosInput<'a, T>(&'a mut T);
1980
1981impl<'a, T> AppendZerosInput<'a, T> {
1982 pub fn new(input: &'a mut T) -> Self {
1984 Self(input)
1985 }
1986}
1987
1988impl<'a, T: codec::Input> codec::Input for AppendZerosInput<'a, T> {
1989 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
1990 Ok(None)
1991 }
1992
1993 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
1994 let remaining = self.0.remaining_len()?;
1995 let completed = if let Some(n) = remaining {
1996 let readable = into.len().min(n);
1997 self.0.read(&mut into[..readable])?;
1999 readable
2000 } else {
2001 let mut i = 0;
2003 while i < into.len() {
2004 if let Ok(b) = self.0.read_byte() {
2005 into[i] = b;
2006 i += 1;
2007 } else {
2008 break;
2009 }
2010 }
2011 i
2012 };
2013 for i in &mut into[completed..] {
2015 *i = 0;
2016 }
2017 Ok(())
2018 }
2019}
2020
2021pub struct TrailingZeroInput<'a>(&'a [u8]);
2023
2024impl<'a> TrailingZeroInput<'a> {
2025 pub fn new(data: &'a [u8]) -> Self {
2027 Self(data)
2028 }
2029
2030 pub fn zeroes() -> Self {
2032 Self::new(&[][..])
2033 }
2034}
2035
2036impl<'a> codec::Input for TrailingZeroInput<'a> {
2037 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
2038 Ok(None)
2039 }
2040
2041 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
2042 let len_from_inner = into.len().min(self.0.len());
2043 into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]);
2044 for i in &mut into[len_from_inner..] {
2045 *i = 0;
2046 }
2047 self.0 = &self.0[len_from_inner..];
2048
2049 Ok(())
2050 }
2051}
2052
2053pub trait AccountIdConversion<AccountId>: Sized {
2055 fn into_account_truncating(&self) -> AccountId {
2058 self.into_sub_account_truncating(&())
2059 }
2060
2061 fn try_into_account(&self) -> Option<AccountId> {
2064 self.try_into_sub_account(&())
2065 }
2066
2067 fn try_from_account(a: &AccountId) -> Option<Self> {
2069 Self::try_from_sub_account::<()>(a).map(|x| x.0)
2070 }
2071
2072 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> AccountId;
2086
2087 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<AccountId>;
2091
2092 fn try_from_sub_account<S: Decode>(x: &AccountId) -> Option<(Self, S)>;
2094}
2095
2096impl<T: Encode + Decode, Id: Encode + Decode + TypeId> AccountIdConversion<T> for Id {
2099 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> T {
2103 (Id::TYPE_ID, self, sub)
2104 .using_encoded(|b| T::decode(&mut TrailingZeroInput(b)))
2105 .expect("All byte sequences are valid `AccountIds`; qed")
2106 }
2107
2108 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<T> {
2110 let encoded_seed = (Id::TYPE_ID, self, sub).encode();
2111 let account = T::decode(&mut TrailingZeroInput(&encoded_seed))
2112 .expect("All byte sequences are valid `AccountIds`; qed");
2113 if encoded_seed.len() <= account.encoded_size() {
2116 Some(account)
2117 } else {
2118 None
2119 }
2120 }
2121
2122 fn try_from_sub_account<S: Decode>(x: &T) -> Option<(Self, S)> {
2123 x.using_encoded(|d| {
2124 if d[0..4] != Id::TYPE_ID {
2125 return None;
2126 }
2127 let mut cursor = &d[4..];
2128 let result = Decode::decode(&mut cursor).ok()?;
2129 if cursor.iter().all(|x| *x == 0) {
2130 Some(result)
2131 } else {
2132 None
2133 }
2134 })
2135 }
2136}
2137
2138#[macro_export]
2145macro_rules! count {
2146 ($f:ident ($($x:tt)*) ) => ();
2147 ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); };
2148 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); };
2149 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); };
2150 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => {
2151 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3);
2152 };
2153 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => {
2154 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4);
2155 };
2156}
2157
2158#[doc(hidden)]
2159#[macro_export]
2160macro_rules! impl_opaque_keys_inner {
2161 (
2162 $( #[ $attr:meta ] )*
2163 pub struct $name:ident {
2164 $(
2165 $( #[ $inner_attr:meta ] )*
2166 pub $field:ident: $type:ty,
2167 )*
2168 },
2169 $crate_path:path,
2170 ) => {
2171 $( #[ $attr ] )*
2172 #[doc = concat!("Generated by [`impl_opaque_keys!`](", stringify!($crate_path),"::impl_opaque_keys).")]
2174 #[derive(
2175 Clone, PartialEq, Eq,
2176 $crate::codec::Encode,
2177 $crate::codec::Decode,
2178 $crate::codec::DecodeWithMemTracking,
2179 $crate::scale_info::TypeInfo,
2180 Debug,
2181 )]
2182 pub struct $name {
2183 $(
2184 $( #[ $inner_attr ] )*
2185 pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public,
2186 )*
2187 }
2188
2189 impl $name {
2190 #[allow(dead_code)]
2203 pub fn generate(
2204 owner: &[u8],
2205 seed: Option<$crate::sp_std::vec::Vec<u8>>,
2206 ) -> $crate::traits::GeneratedSessionKeys<
2207 Self,
2208 (
2209 $(
2210 <
2211 <$type as $crate::BoundToRuntimeAppPublic>::Public
2212 as $crate::RuntimeAppPublic
2213 >::ProofOfPossession
2214 ),*
2215 )
2216 > {
2217 let mut keys = Self {
2218 $(
2219 $field: <
2220 <
2221 $type as $crate::BoundToRuntimeAppPublic
2222 >::Public as $crate::RuntimeAppPublic
2223 >::generate_pair(seed.clone()),
2224 )*
2225 };
2226
2227 let proof = keys.create_ownership_proof(owner)
2228 .expect("Private key that was generated a moment ago, should exist; qed");
2229
2230 $crate::traits::GeneratedSessionKeys {
2231 keys,
2232 proof
2233 }
2234 }
2235
2236 #[allow(dead_code)]
2238 pub fn into_raw_public_keys(
2239 self,
2240 ) -> $crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)> {
2241 let mut keys = Vec::new();
2242 $(
2243 keys.push((
2244 $crate::RuntimeAppPublic::to_raw_vec(&self.$field),
2245 <
2246 <
2247 $type as $crate::BoundToRuntimeAppPublic
2248 >::Public as $crate::RuntimeAppPublic
2249 >::ID,
2250 ));
2251 )*
2252
2253 keys
2254 }
2255
2256 #[allow(dead_code)]
2261 pub fn decode_into_raw_public_keys(
2262 encoded: &[u8],
2263 ) -> Option<$crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)>> {
2264 <Self as $crate::codec::Decode>::decode(&mut &encoded[..])
2265 .ok()
2266 .map(|s| s.into_raw_public_keys())
2267 }
2268
2269 #[allow(dead_code)]
2279 pub fn create_ownership_proof(
2280 &mut self,
2281 owner: &[u8],
2282 ) -> $crate::sp_std::result::Result<
2283 (
2284 $(
2285 <
2286 <$type as $crate::BoundToRuntimeAppPublic>::Public
2287 as $crate::RuntimeAppPublic
2288 >::ProofOfPossession
2289 ),*
2290 ),
2291 ()
2292 > {
2293 let res = ($(
2294 $crate::RuntimeAppPublic::generate_proof_of_possession(&mut self.$field, &owner).ok_or(())?
2295 ),*);
2296
2297 Ok(res)
2298 }
2299 }
2300
2301 impl $crate::traits::OpaqueKeys for $name {
2302 type KeyTypeIdProviders = ( $( $type, )* );
2303
2304 fn key_ids() -> &'static [$crate::KeyTypeId] {
2305 &[
2306 $(
2307 <
2308 <
2309 $type as $crate::BoundToRuntimeAppPublic
2310 >::Public as $crate::RuntimeAppPublic
2311 >::ID
2312 ),*
2313 ]
2314 }
2315
2316 fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] {
2317 match i {
2318 $(
2319 i if i == <
2320 <
2321 $type as $crate::BoundToRuntimeAppPublic
2322 >::Public as $crate::RuntimeAppPublic
2323 >::ID =>
2324 self.$field.as_ref(),
2325 )*
2326 _ => &[],
2327 }
2328 }
2329
2330 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool {
2331 let Ok(proof) = <($(
2333 <
2334 <
2335 $type as $crate::BoundToRuntimeAppPublic
2336 >::Public as $crate::RuntimeAppPublic
2337 >::ProofOfPossession
2338 ),*) as $crate::codec::DecodeAll>::decode_all(&mut &proof[..]) else {
2339 return false
2340 };
2341
2342 let ( $( $field ),* ) = proof;
2344
2345 $(
2347 let valid = $crate::RuntimeAppPublic::verify_proof_of_possession(&self.$field, &owner, &$field);
2348
2349 if !valid {
2350 return false
2352 }
2353 )*
2354
2355 true
2356 }
2357 }
2358 };
2359}
2360
2361#[derive(Debug, Clone, Encode, Decode, TypeInfo)]
2368pub struct GeneratedSessionKeys<Keys, Proof> {
2369 pub keys: Keys,
2371 pub proof: Proof,
2373}
2374
2375#[macro_export]
2405#[cfg(any(feature = "serde", feature = "std"))]
2406macro_rules! impl_opaque_keys {
2407 {
2408 $( #[ $attr:meta ] )*
2409 pub struct $name:ident {
2410 $(
2411 $( #[ $inner_attr:meta ] )*
2412 pub $field:ident: $type:ty,
2413 )*
2414 }
2415 } => {
2416 $crate::paste::paste! {
2417 use $crate::serde as [< __opaque_keys_serde_import__ $name >];
2418
2419 $crate::impl_opaque_keys_inner! {
2420 $( #[ $attr ] )*
2421 #[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
2422 #[serde(crate = "__opaque_keys_serde_import__" $name)]
2423 pub struct $name {
2424 $(
2425 $( #[ $inner_attr ] )*
2426 pub $field: $type,
2427 )*
2428 },
2429 $crate,
2430 }
2431 }
2432 }
2433}
2434
2435#[macro_export]
2436#[cfg(all(not(feature = "std"), not(feature = "serde")))]
2437#[doc(hidden)]
2438macro_rules! impl_opaque_keys {
2439 {
2440 $( #[ $attr:meta ] )*
2441 pub struct $name:ident {
2442 $(
2443 $( #[ $inner_attr:meta ] )*
2444 pub $field:ident: $type:ty,
2445 )*
2446 }
2447 } => {
2448 $crate::impl_opaque_keys_inner! {
2449 $( #[ $attr ] )*
2450 pub struct $name {
2451 $(
2452 $( #[ $inner_attr ] )*
2453 pub $field: $type,
2454 )*
2455 },
2456 $crate,
2457 }
2458 }
2459}
2460
2461pub trait Printable {
2463 fn print(&self);
2465}
2466
2467impl<T: Printable> Printable for &T {
2468 fn print(&self) {
2469 (*self).print()
2470 }
2471}
2472
2473impl Printable for u8 {
2474 fn print(&self) {
2475 (*self as u64).print()
2476 }
2477}
2478
2479impl Printable for u32 {
2480 fn print(&self) {
2481 (*self as u64).print()
2482 }
2483}
2484
2485impl Printable for usize {
2486 fn print(&self) {
2487 (*self as u64).print()
2488 }
2489}
2490
2491impl Printable for u64 {
2492 fn print(&self) {
2493 sp_io::misc::print_num(*self);
2494 }
2495}
2496
2497impl Printable for &[u8] {
2498 fn print(&self) {
2499 sp_io::misc::print_hex(self);
2500 }
2501}
2502
2503impl<const N: usize> Printable for [u8; N] {
2504 fn print(&self) {
2505 sp_io::misc::print_hex(&self[..]);
2506 }
2507}
2508
2509impl Printable for &str {
2510 fn print(&self) {
2511 sp_io::misc::print_utf8(self.as_bytes());
2512 }
2513}
2514
2515impl Printable for bool {
2516 fn print(&self) {
2517 if *self {
2518 "true".print()
2519 } else {
2520 "false".print()
2521 }
2522 }
2523}
2524
2525impl Printable for sp_weights::Weight {
2526 fn print(&self) {
2527 self.ref_time().print()
2528 }
2529}
2530
2531impl Printable for () {
2532 fn print(&self) {
2533 "()".print()
2534 }
2535}
2536
2537#[impl_for_tuples(1, 12)]
2538impl Printable for Tuple {
2539 fn print(&self) {
2540 for_tuples!( #( Tuple.print(); )* )
2541 }
2542}
2543
2544#[cfg(feature = "std")]
2546pub trait BlockIdTo<Block: self::Block> {
2547 type Error: std::error::Error;
2549
2550 fn to_hash(
2552 &self,
2553 block_id: &crate::generic::BlockId<Block>,
2554 ) -> Result<Option<Block::Hash>, Self::Error>;
2555
2556 fn to_number(
2558 &self,
2559 block_id: &crate::generic::BlockId<Block>,
2560 ) -> Result<Option<NumberFor<Block>>, Self::Error>;
2561}
2562
2563pub trait BlockNumberProvider {
2565 type BlockNumber: Codec
2567 + DecodeWithMemTracking
2568 + Clone
2569 + Ord
2570 + Eq
2571 + AtLeast32BitUnsigned
2572 + TypeInfo
2573 + Debug
2574 + MaxEncodedLen
2575 + Copy
2576 + EncodeLike
2577 + Default;
2578
2579 fn current_block_number() -> Self::BlockNumber;
2595
2596 #[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
2602 fn set_block_number(_block: Self::BlockNumber) {}
2603}
2604
2605impl BlockNumberProvider for () {
2606 type BlockNumber = u32;
2607 fn current_block_number() -> Self::BlockNumber {
2608 0
2609 }
2610}
2611
2612#[cfg(test)]
2613mod tests {
2614 use super::*;
2615 use crate::codec::{Decode, Encode, Input};
2616 #[cfg(feature = "bls-experimental")]
2617 use sp_core::ecdsa_bls381;
2618 use sp_core::{
2619 crypto::{Pair, UncheckedFrom},
2620 ecdsa, ed25519,
2621 proof_of_possession::ProofOfPossessionGenerator,
2622 sr25519,
2623 };
2624 use std::sync::Arc;
2625
2626 macro_rules! signature_verify_test {
2627 ($algorithm:ident) => {
2628 let msg = &b"test-message"[..];
2629 let wrong_msg = &b"test-msg"[..];
2630 let (pair, _) = $algorithm::Pair::generate();
2631
2632 let signature = pair.sign(&msg);
2633 assert!($algorithm::Pair::verify(&signature, msg, &pair.public()));
2634
2635 assert!(signature.verify(msg, &pair.public()));
2636 assert!(!signature.verify(wrong_msg, &pair.public()));
2637 };
2638 }
2639
2640 mod t {
2641 use sp_application_crypto::{app_crypto, sr25519};
2642 use sp_core::crypto::KeyTypeId;
2643 app_crypto!(sr25519, KeyTypeId(*b"test"));
2644 }
2645
2646 #[test]
2647 fn app_verify_works() {
2648 use super::AppVerify;
2649 use t::*;
2650
2651 let s = Signature::try_from(vec![0; 64]).unwrap();
2652 let _ = s.verify(&[0u8; 100][..], &Public::unchecked_from([0; 32]));
2653 }
2654
2655 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2656 struct U128Value(u128);
2657 impl super::TypeId for U128Value {
2658 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0x0d, 0xf0];
2659 }
2660 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2663 struct U32Value(u32);
2664 impl super::TypeId for U32Value {
2665 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
2666 }
2667 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2670 struct U16Value(u16);
2671 impl super::TypeId for U16Value {
2672 const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
2673 }
2674 type AccountId = u64;
2677
2678 #[test]
2679 fn into_account_truncating_should_work() {
2680 let r: AccountId = U32Value::into_account_truncating(&U32Value(0xdeadbeef));
2681 assert_eq!(r, 0x_deadbeef_cafef00d);
2682 }
2683
2684 #[test]
2685 fn try_into_account_should_work() {
2686 let r: AccountId = U32Value::try_into_account(&U32Value(0xdeadbeef)).unwrap();
2687 assert_eq!(r, 0x_deadbeef_cafef00d);
2688
2689 let maybe: Option<AccountId> = U128Value::try_into_account(&U128Value(u128::MAX));
2691 assert!(maybe.is_none());
2692 }
2693
2694 #[test]
2695 fn try_from_account_should_work() {
2696 let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
2697 assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
2698 }
2699
2700 #[test]
2701 fn into_account_truncating_with_fill_should_work() {
2702 let r: AccountId = U16Value::into_account_truncating(&U16Value(0xc0da));
2703 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2704 }
2705
2706 #[test]
2707 fn try_into_sub_account_should_work() {
2708 let r: AccountId = U16Value::try_into_account(&U16Value(0xc0da)).unwrap();
2709 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2710
2711 let maybe: Option<AccountId> = U16Value::try_into_sub_account(
2712 &U16Value(0xc0da),
2713 "a really large amount of additional encoded information which will certainly overflow the account id type ;)"
2714 );
2715
2716 assert!(maybe.is_none())
2717 }
2718
2719 #[test]
2720 fn try_from_account_with_fill_should_work() {
2721 let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
2722 assert_eq!(r.unwrap(), U16Value(0xc0da));
2723 }
2724
2725 #[test]
2726 fn bad_try_from_account_should_fail() {
2727 let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
2728 assert!(r.is_none());
2729 let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
2730 assert!(r.is_none());
2731 }
2732
2733 #[test]
2734 fn trailing_zero_should_work() {
2735 let mut t = super::TrailingZeroInput(&[1, 2, 3]);
2736 assert_eq!(t.remaining_len(), Ok(None));
2737 let mut buffer = [0u8; 2];
2738 assert_eq!(t.read(&mut buffer), Ok(()));
2739 assert_eq!(t.remaining_len(), Ok(None));
2740 assert_eq!(buffer, [1, 2]);
2741 assert_eq!(t.read(&mut buffer), Ok(()));
2742 assert_eq!(t.remaining_len(), Ok(None));
2743 assert_eq!(buffer, [3, 0]);
2744 assert_eq!(t.read(&mut buffer), Ok(()));
2745 assert_eq!(t.remaining_len(), Ok(None));
2746 assert_eq!(buffer, [0, 0]);
2747 }
2748
2749 #[test]
2750 fn ed25519_verify_works() {
2751 signature_verify_test!(ed25519);
2752 }
2753
2754 #[test]
2755 fn sr25519_verify_works() {
2756 signature_verify_test!(sr25519);
2757 }
2758
2759 #[test]
2760 fn ecdsa_verify_works() {
2761 signature_verify_test!(ecdsa);
2762 }
2763
2764 #[test]
2765 #[cfg(feature = "bls-experimental")]
2766 fn ecdsa_bls381_verify_works() {
2767 signature_verify_test!(ecdsa_bls381);
2768 }
2769
2770 pub struct Sr25519Key;
2771 impl crate::BoundToRuntimeAppPublic for Sr25519Key {
2772 type Public = sp_application_crypto::sr25519::AppPublic;
2773 }
2774
2775 pub struct Ed25519Key;
2776 impl crate::BoundToRuntimeAppPublic for Ed25519Key {
2777 type Public = sp_application_crypto::ed25519::AppPublic;
2778 }
2779
2780 pub struct EcdsaKey;
2781 impl crate::BoundToRuntimeAppPublic for EcdsaKey {
2782 type Public = sp_application_crypto::ecdsa::AppPublic;
2783 }
2784
2785 impl_opaque_keys! {
2786 pub struct SessionKeys {
2788 pub sr25519: Sr25519Key,
2789 pub ed25519: Ed25519Key,
2790 pub ecdsa: EcdsaKey,
2791 }
2792 }
2793
2794 #[test]
2795 fn opaque_keys_ownership_proof_works() {
2796 let mut sr25519 = sp_core::sr25519::Pair::generate().0;
2797 let mut ed25519 = sp_core::ed25519::Pair::generate().0;
2798 let mut ecdsa = sp_core::ecdsa::Pair::generate().0;
2799
2800 let session_keys = SessionKeys {
2801 sr25519: sr25519.public().into(),
2802 ed25519: ed25519.public().into(),
2803 ecdsa: ecdsa.public().into(),
2804 };
2805
2806 let owner = &b"owner"[..];
2807
2808 let sr25519_sig = sr25519.generate_proof_of_possession(&owner);
2809 let ed25519_sig = ed25519.generate_proof_of_possession(&owner);
2810 let ecdsa_sig = ecdsa.generate_proof_of_possession(&owner);
2811
2812 for invalidate in [None, Some(0), Some(1), Some(2)] {
2813 let proof = if let Some(invalidate) = invalidate {
2814 match invalidate {
2815 0 => (
2816 sr25519.generate_proof_of_possession(&b"invalid"[..]),
2817 &ed25519_sig,
2818 &ecdsa_sig,
2819 )
2820 .encode(),
2821 1 => (
2822 &sr25519_sig,
2823 ed25519.generate_proof_of_possession(&b"invalid"[..]),
2824 &ecdsa_sig,
2825 )
2826 .encode(),
2827 2 => (
2828 &sr25519_sig,
2829 &ed25519_sig,
2830 ecdsa.generate_proof_of_possession(&b"invalid"[..]),
2831 )
2832 .encode(),
2833 _ => unreachable!(),
2834 }
2835 } else {
2836 (&sr25519_sig, &ed25519_sig, &ecdsa_sig).encode()
2837 };
2838
2839 assert_eq!(session_keys.ownership_proof_is_valid(owner, &proof), invalidate.is_none());
2840 }
2841
2842 let proof = (&sr25519_sig, &ed25519_sig, &ecdsa_sig, "hello").encode();
2844 assert!(!session_keys.ownership_proof_is_valid(owner, &proof));
2845
2846 let mut ext = sp_io::TestExternalities::default();
2847 ext.register_extension(sp_keystore::KeystoreExt(Arc::new(
2848 sp_keystore::testing::MemoryKeystore::new(),
2849 )));
2850
2851 ext.execute_with(|| {
2852 let session_keys = SessionKeys::generate(&owner, None);
2853
2854 assert!(session_keys
2855 .keys
2856 .ownership_proof_is_valid(&owner, &session_keys.proof.encode()));
2857 });
2858 }
2859}