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 if !sp_core::ecdsa::is_signature_normalized(self.as_ref()) {
155 return false;
156 }
157 match sp_io::crypto::secp256k1_ecdsa_recover_compressed(
158 self.as_ref(),
159 &sp_io::hashing::blake2_256(msg.get()),
160 ) {
161 Ok(pubkey) => signer.0 == pubkey,
162 _ => false,
163 }
164 }
165}
166
167#[cfg(feature = "bls-experimental")]
168impl Verify for sp_core::ecdsa_bls381::Signature {
169 type Signer = sp_core::ecdsa_bls381::Public;
170 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa_bls381::Public) -> bool {
171 <sp_core::ecdsa_bls381::Pair as sp_core::Pair>::verify(self, msg.get(), signer)
172 }
173}
174
175pub trait AppVerify {
177 type AccountId;
179 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &Self::AccountId) -> bool;
181}
182
183impl<
184 S: Verify<Signer = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic>
185 + From<T>,
186 T: sp_application_crypto::Wraps<Inner = S>
187 + sp_application_crypto::AppCrypto
188 + sp_application_crypto::AppSignature
189 + AsRef<S>
190 + AsMut<S>
191 + From<S>,
192 > AppVerify for T
193where
194 <S as Verify>::Signer: IdentifyAccount<AccountId = <S as Verify>::Signer>,
195 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
196 AccountId = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic,
197 >,
198{
199 type AccountId = <T as AppCrypto>::Public;
200 fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppCrypto>::Public) -> bool {
201 use sp_application_crypto::IsWrappedBy;
202 let inner: &S = self.as_ref();
203 let inner_pubkey =
204 <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(
205 signer,
206 );
207 Verify::verify(inner, msg, inner_pubkey)
208 }
209}
210
211#[derive(Encode, Decode, Debug)]
213pub struct BadOrigin;
214
215impl From<BadOrigin> for &'static str {
216 fn from(_: BadOrigin) -> &'static str {
217 "Bad origin"
218 }
219}
220
221#[derive(Encode, Decode, Debug)]
223pub struct LookupError;
224
225impl From<LookupError> for &'static str {
226 fn from(_: LookupError) -> &'static str {
227 "Can not lookup"
228 }
229}
230
231impl From<LookupError> for TransactionValidityError {
232 fn from(_: LookupError) -> Self {
233 UnknownTransaction::CannotLookup.into()
234 }
235}
236
237pub trait Lookup {
239 type Source;
241 type Target;
243 fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError>;
245}
246
247pub trait StaticLookup {
251 type Source: Codec + Clone + PartialEq + Debug + TypeInfo;
253 type Target;
255 fn lookup(s: Self::Source) -> Result<Self::Target, LookupError>;
257 fn unlookup(t: Self::Target) -> Self::Source;
259}
260
261#[derive(Clone, Copy, PartialEq, Eq)]
263pub struct IdentityLookup<T>(PhantomData<T>);
264impl<T> Default for IdentityLookup<T> {
265 fn default() -> Self {
266 Self(PhantomData::<T>::default())
267 }
268}
269
270impl<T: Codec + Clone + PartialEq + Debug + TypeInfo> StaticLookup for IdentityLookup<T> {
271 type Source = T;
272 type Target = T;
273 fn lookup(x: T) -> Result<T, LookupError> {
274 Ok(x)
275 }
276 fn unlookup(x: T) -> T {
277 x
278 }
279}
280
281impl<T> Lookup for IdentityLookup<T> {
282 type Source = T;
283 type Target = T;
284 fn lookup(&self, x: T) -> Result<T, LookupError> {
285 Ok(x)
286 }
287}
288
289pub struct AccountIdLookup<AccountId, AccountIndex>(PhantomData<(AccountId, AccountIndex)>);
291impl<AccountId, AccountIndex> StaticLookup for AccountIdLookup<AccountId, AccountIndex>
292where
293 AccountId: Codec + Clone + PartialEq + Debug,
294 AccountIndex: Codec + Clone + PartialEq + Debug,
295 crate::MultiAddress<AccountId, AccountIndex>: Codec + StaticTypeInfo,
296{
297 type Source = crate::MultiAddress<AccountId, AccountIndex>;
298 type Target = AccountId;
299 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
300 match x {
301 crate::MultiAddress::Id(i) => Ok(i),
302 _ => Err(LookupError),
303 }
304 }
305 fn unlookup(x: Self::Target) -> Self::Source {
306 crate::MultiAddress::Id(x)
307 }
308}
309
310impl<A, B> StaticLookup for (A, B)
312where
313 A: StaticLookup,
314 B: StaticLookup<Source = A::Source, Target = A::Target>,
315{
316 type Source = A::Source;
317 type Target = A::Target;
318
319 fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
320 A::lookup(x.clone()).or_else(|_| B::lookup(x))
321 }
322 fn unlookup(x: Self::Target) -> Self::Source {
323 A::unlookup(x)
324 }
325}
326
327pub trait Morph<A> {
330 type Outcome;
332
333 fn morph(a: A) -> Self::Outcome;
335}
336
337impl<T> Morph<T> for Identity {
339 type Outcome = T;
340 fn morph(a: T) -> T {
341 a
342 }
343}
344
345pub trait TryMorph<A> {
348 type Outcome;
350
351 fn try_morph(a: A) -> Result<Self::Outcome, ()>;
353}
354
355impl<T> TryMorph<T> for Identity {
357 type Outcome = T;
358 fn try_morph(a: T) -> Result<T, ()> {
359 Ok(a)
360 }
361}
362
363pub struct MorphInto<T>(core::marker::PhantomData<T>);
365impl<T, A: Into<T>> Morph<A> for MorphInto<T> {
366 type Outcome = T;
367 fn morph(a: A) -> T {
368 a.into()
369 }
370}
371
372pub struct TryMorphInto<T>(core::marker::PhantomData<T>);
374impl<T, A: TryInto<T>> TryMorph<A> for TryMorphInto<T> {
375 type Outcome = T;
376 fn try_morph(a: A) -> Result<T, ()> {
377 a.try_into().map_err(|_| ())
378 }
379}
380
381pub struct TakeFirst;
383impl<T1> Morph<(T1,)> for TakeFirst {
384 type Outcome = T1;
385 fn morph(a: (T1,)) -> T1 {
386 a.0
387 }
388}
389impl<T1, T2> Morph<(T1, T2)> for TakeFirst {
390 type Outcome = T1;
391 fn morph(a: (T1, T2)) -> T1 {
392 a.0
393 }
394}
395impl<T1, T2, T3> Morph<(T1, T2, T3)> for TakeFirst {
396 type Outcome = T1;
397 fn morph(a: (T1, T2, T3)) -> T1 {
398 a.0
399 }
400}
401impl<T1, T2, T3, T4> Morph<(T1, T2, T3, T4)> for TakeFirst {
402 type Outcome = T1;
403 fn morph(a: (T1, T2, T3, T4)) -> T1 {
404 a.0
405 }
406}
407
408#[macro_export]
444macro_rules! morph_types {
445 (
446 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ()
447 ) => {
448 $( #[doc = $doc] )* $vq struct $name;
449 };
450 (
451 @DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ( $( $bound_id:ident ),+ )
452 ) => {
453 $( #[doc = $doc] )*
454 $vq struct $name < $($bound_id,)* > ( $crate::traits::PhantomData< ( $($bound_id,)* ) > ) ;
455 };
456 (
457 @IMPL $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
458 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
459 ) => {
460 impl<$($bounds)*> $crate::traits::Morph<$var_type> for $name $( $where )? {
461 type Outcome = $outcome;
462 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
463 }
464 };
465 (
466 @IMPL_TRY $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
467 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
468 ) => {
469 impl<$($bounds)*> $crate::traits::TryMorph<$var_type> for $name $( $where )? {
470 type Outcome = $outcome;
471 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
472 }
473 };
474 (
475 @IMPL $name:ty : () ( $( $where:tt )* )
476 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
477 ) => {
478 impl $crate::traits::Morph<$var_type> for $name $( $where )? {
479 type Outcome = $outcome;
480 fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
481 }
482 };
483 (
484 @IMPL_TRY $name:ty : () ( $( $where:tt )* )
485 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
486 ) => {
487 impl $crate::traits::TryMorph<$var_type> for $name $( $where )? {
488 type Outcome = $outcome;
489 fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
490 }
491 };
492 (
493 @IMPL_BOTH $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
494 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
495 ) => {
496 morph_types! {
497 @IMPL $name : ($($bounds)*) ($($where)*)
498 = |$var: $var_type| -> $outcome { $( $ex )* }
499 }
500 morph_types! {
501 @IMPL_TRY $name : ($($bounds)*) ($($where)*)
502 = |$var: $var_type| -> $outcome { Ok({$( $ex )*}) }
503 }
504 };
505
506 (
507 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
508 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
509 $(: $type:tt)?
510 = |_| -> $outcome:ty { $( $ex:expr )* };
511 $( $rest:tt )*
512 ) => {
513 morph_types! {
514 $( #[doc = $doc] )* $vq type $name
515 $( < $( $bound_id $( : $bound_head $( | $bound_tail )* )? ),+ > )?
516 EXTRA_GENERIC(X)
517 $(: $type)?
518 = |_x: X| -> $outcome { $( $ex )* };
519 $( $rest )*
520 }
521 };
522 (
523 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
524 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
525 $( EXTRA_GENERIC ($extra:ident) )?
526 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
527 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
528 $( $rest:tt )*
529 ) => {
530 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
531 morph_types! {
532 @IMPL_BOTH $name $( < $( $bound_id ),* > )? :
533 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
534 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
535 = |$var: $var_type| -> $outcome { $( $ex )* }
536 }
537 morph_types!{ $($rest)* }
538 };
539 (
540 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
541 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
542 $( EXTRA_GENERIC ($extra:ident) )?
543 : Morph
544 = |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
545 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
546 $( $rest:tt )*
547 ) => {
548 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
549 morph_types! {
550 @IMPL $name $( < $( $bound_id ),* > )? :
551 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
552 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
553 = |$var: $var_type| -> $outcome { $( $ex )* }
554 }
555 morph_types!{ $($rest)* }
556 };
557 (
558 $( #[doc = $doc:expr] )* $vq:vis type $name:ident
559 $( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
560 $( EXTRA_GENERIC ($extra:ident) )?
561 : TryMorph
562 = |$var:ident: $var_type:ty| -> Result<$outcome:ty, ()> { $( $ex:expr )* }
563 $( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
564 $( $rest:tt )*
565 ) => {
566 morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
567 morph_types! {
568 @IMPL_TRY $name $( < $( $bound_id ),* > )? :
569 ( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
570 ( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
571 = |$var: $var_type| -> $outcome { $( $ex )* }
572 }
573 morph_types!{ $($rest)* }
574 };
575 () => {}
576}
577
578morph_types! {
579 pub type Replace<V: TypedGet> = |_| -> V::Type { V::get() };
581
582 pub type ReplaceWithDefault<V: Default> = |_| -> V { Default::default() };
584
585 pub type ReduceBy<N: TypedGet> = |r: N::Type| -> N::Type {
587 r.checked_sub(&N::get()).unwrap_or(Zero::zero())
588 } where N::Type: CheckedSub | Zero;
589
590 pub type CheckedReduceBy<N: TypedGet>: TryMorph = |r: N::Type| -> Result<N::Type, ()> {
593 r.checked_sub(&N::get()).ok_or(())
594 } where N::Type: CheckedSub;
595
596 pub type MorphWithUpperLimit<L: TypedGet, M>: TryMorph = |r: L::Type| -> Result<L::Type, ()> {
598 M::try_morph(r).map(|m| m.min(L::get()))
599 } where L::Type: Ord, M: TryMorph<L::Type, Outcome = L::Type>;
600}
601
602pub trait Convert<A, B> {
604 fn convert(a: A) -> B;
606}
607
608impl<A, B: Default> Convert<A, B> for () {
609 fn convert(_: A) -> B {
610 Default::default()
611 }
612}
613
614pub trait ConvertBack<A, B>: Convert<A, B> {
618 fn convert_back(b: B) -> A;
620}
621
622pub trait MaybeConvert<A, B> {
624 fn maybe_convert(a: A) -> Option<B>;
626}
627
628#[impl_trait_for_tuples::impl_for_tuples(30)]
629impl<A: Clone, B> MaybeConvert<A, B> for Tuple {
630 fn maybe_convert(a: A) -> Option<B> {
631 for_tuples!( #(
632 match Tuple::maybe_convert(a.clone()) {
633 Some(b) => return Some(b),
634 None => {},
635 }
636 )* );
637 None
638 }
639}
640
641pub trait MaybeConvertBack<A, B>: MaybeConvert<A, B> {
644 fn maybe_convert_back(b: B) -> Option<A>;
646}
647
648#[impl_trait_for_tuples::impl_for_tuples(30)]
649impl<A: Clone, B: Clone> MaybeConvertBack<A, B> for Tuple {
650 fn maybe_convert_back(b: B) -> Option<A> {
651 for_tuples!( #(
652 match Tuple::maybe_convert_back(b.clone()) {
653 Some(a) => return Some(a),
654 None => {},
655 }
656 )* );
657 None
658 }
659}
660
661pub trait TryConvert<A, B> {
664 fn try_convert(a: A) -> Result<B, A>;
666}
667
668#[impl_trait_for_tuples::impl_for_tuples(30)]
669impl<A, B> TryConvert<A, B> for Tuple {
670 fn try_convert(a: A) -> Result<B, A> {
671 for_tuples!( #(
672 let a = match Tuple::try_convert(a) {
673 Ok(b) => return Ok(b),
674 Err(a) => a,
675 };
676 )* );
677 Err(a)
678 }
679}
680
681pub trait TryConvertBack<A, B>: TryConvert<A, B> {
684 fn try_convert_back(b: B) -> Result<A, B>;
687}
688
689#[impl_trait_for_tuples::impl_for_tuples(30)]
690impl<A, B> TryConvertBack<A, B> for Tuple {
691 fn try_convert_back(b: B) -> Result<A, B> {
692 for_tuples!( #(
693 let b = match Tuple::try_convert_back(b) {
694 Ok(a) => return Ok(a),
695 Err(b) => b,
696 };
697 )* );
698 Err(b)
699 }
700}
701
702pub trait MaybeEquivalence<A, B> {
704 fn convert(a: &A) -> Option<B>;
706 fn convert_back(b: &B) -> Option<A>;
708}
709
710#[impl_trait_for_tuples::impl_for_tuples(30)]
711impl<A, B> MaybeEquivalence<A, B> for Tuple {
712 fn convert(a: &A) -> Option<B> {
713 for_tuples!( #(
714 match Tuple::convert(a) {
715 Some(b) => return Some(b),
716 None => {},
717 }
718 )* );
719 None
720 }
721 fn convert_back(b: &B) -> Option<A> {
722 for_tuples!( #(
723 match Tuple::convert_back(b) {
724 Some(a) => return Some(a),
725 None => {},
726 }
727 )* );
728 None
729 }
730}
731
732pub struct ConvertToValue<T>(core::marker::PhantomData<T>);
735impl<X, Y, T: Get<Y>> Convert<X, Y> for ConvertToValue<T> {
736 fn convert(_: X) -> Y {
737 T::get()
738 }
739}
740impl<X, Y, T: Get<Y>> MaybeConvert<X, Y> for ConvertToValue<T> {
741 fn maybe_convert(_: X) -> Option<Y> {
742 Some(T::get())
743 }
744}
745impl<X, Y, T: Get<Y>> MaybeConvertBack<X, Y> for ConvertToValue<T> {
746 fn maybe_convert_back(_: Y) -> Option<X> {
747 None
748 }
749}
750impl<X, Y, T: Get<Y>> TryConvert<X, Y> for ConvertToValue<T> {
751 fn try_convert(_: X) -> Result<Y, X> {
752 Ok(T::get())
753 }
754}
755impl<X, Y, T: Get<Y>> TryConvertBack<X, Y> for ConvertToValue<T> {
756 fn try_convert_back(y: Y) -> Result<X, Y> {
757 Err(y)
758 }
759}
760impl<X, Y, T: Get<Y>> MaybeEquivalence<X, Y> for ConvertToValue<T> {
761 fn convert(_: &X) -> Option<Y> {
762 Some(T::get())
763 }
764 fn convert_back(_: &Y) -> Option<X> {
765 None
766 }
767}
768
769pub struct Identity;
771impl<T> Convert<T, T> for Identity {
772 fn convert(a: T) -> T {
773 a
774 }
775}
776impl<T> ConvertBack<T, T> for Identity {
777 fn convert_back(a: T) -> T {
778 a
779 }
780}
781impl<T> MaybeConvert<T, T> for Identity {
782 fn maybe_convert(a: T) -> Option<T> {
783 Some(a)
784 }
785}
786impl<T> MaybeConvertBack<T, T> for Identity {
787 fn maybe_convert_back(a: T) -> Option<T> {
788 Some(a)
789 }
790}
791impl<T> TryConvert<T, T> for Identity {
792 fn try_convert(a: T) -> Result<T, T> {
793 Ok(a)
794 }
795}
796impl<T> TryConvertBack<T, T> for Identity {
797 fn try_convert_back(a: T) -> Result<T, T> {
798 Ok(a)
799 }
800}
801impl<T: Clone> MaybeEquivalence<T, T> for Identity {
802 fn convert(a: &T) -> Option<T> {
803 Some(a.clone())
804 }
805 fn convert_back(a: &T) -> Option<T> {
806 Some(a.clone())
807 }
808}
809
810pub struct ConvertInto;
812impl<A: Into<B>, B> Convert<A, B> for ConvertInto {
813 fn convert(a: A) -> B {
814 a.into()
815 }
816}
817impl<A: Into<B>, B> MaybeConvert<A, B> for ConvertInto {
818 fn maybe_convert(a: A) -> Option<B> {
819 Some(a.into())
820 }
821}
822impl<A: Into<B>, B: Into<A>> MaybeConvertBack<A, B> for ConvertInto {
823 fn maybe_convert_back(b: B) -> Option<A> {
824 Some(b.into())
825 }
826}
827impl<A: Into<B>, B> TryConvert<A, B> for ConvertInto {
828 fn try_convert(a: A) -> Result<B, A> {
829 Ok(a.into())
830 }
831}
832impl<A: Into<B>, B: Into<A>> TryConvertBack<A, B> for ConvertInto {
833 fn try_convert_back(b: B) -> Result<A, B> {
834 Ok(b.into())
835 }
836}
837impl<A: Clone + Into<B>, B: Clone + Into<A>> MaybeEquivalence<A, B> for ConvertInto {
838 fn convert(a: &A) -> Option<B> {
839 Some(a.clone().into())
840 }
841 fn convert_back(b: &B) -> Option<A> {
842 Some(b.clone().into())
843 }
844}
845
846pub struct TryConvertInto;
848impl<A: Clone + TryInto<B>, B> MaybeConvert<A, B> for TryConvertInto {
849 fn maybe_convert(a: A) -> Option<B> {
850 a.clone().try_into().ok()
851 }
852}
853impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeConvertBack<A, B> for TryConvertInto {
854 fn maybe_convert_back(b: B) -> Option<A> {
855 b.clone().try_into().ok()
856 }
857}
858impl<A: Clone + TryInto<B>, B> TryConvert<A, B> for TryConvertInto {
859 fn try_convert(a: A) -> Result<B, A> {
860 a.clone().try_into().map_err(|_| a)
861 }
862}
863impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> TryConvertBack<A, B> for TryConvertInto {
864 fn try_convert_back(b: B) -> Result<A, B> {
865 b.clone().try_into().map_err(|_| b)
866 }
867}
868impl<A: Clone + TryInto<B>, B: Clone + TryInto<A>> MaybeEquivalence<A, B> for TryConvertInto {
869 fn convert(a: &A) -> Option<B> {
870 a.clone().try_into().ok()
871 }
872 fn convert_back(b: &B) -> Option<A> {
873 b.clone().try_into().ok()
874 }
875}
876
877pub trait CheckedConversion {
881 fn checked_from<T>(t: T) -> Option<Self>
887 where
888 Self: TryFrom<T>,
889 {
890 <Self as TryFrom<T>>::try_from(t).ok()
891 }
892 fn checked_into<T>(self) -> Option<T>
898 where
899 Self: TryInto<T>,
900 {
901 <Self as TryInto<T>>::try_into(self).ok()
902 }
903}
904impl<T: Sized> CheckedConversion for T {}
905
906pub trait Scale<Other> {
909 type Output;
911
912 fn mul(self, other: Other) -> Self::Output;
914
915 fn div(self, other: Other) -> Self::Output;
917
918 fn rem(self, other: Other) -> Self::Output;
920}
921macro_rules! impl_scale {
922 ($self:ty, $other:ty) => {
923 impl Scale<$other> for $self {
924 type Output = Self;
925 fn mul(self, other: $other) -> Self::Output {
926 self * (other as Self)
927 }
928 fn div(self, other: $other) -> Self::Output {
929 self / (other as Self)
930 }
931 fn rem(self, other: $other) -> Self::Output {
932 self % (other as Self)
933 }
934 }
935 };
936}
937impl_scale!(u128, u128);
938impl_scale!(u128, u64);
939impl_scale!(u128, u32);
940impl_scale!(u128, u16);
941impl_scale!(u128, u8);
942impl_scale!(u64, u64);
943impl_scale!(u64, u32);
944impl_scale!(u64, u16);
945impl_scale!(u64, u8);
946impl_scale!(u32, u32);
947impl_scale!(u32, u16);
948impl_scale!(u32, u8);
949impl_scale!(u16, u16);
950impl_scale!(u16, u8);
951impl_scale!(u8, u8);
952
953pub trait Clear {
956 fn is_clear(&self) -> bool;
958
959 fn clear() -> Self;
961}
962
963impl<T: Default + Eq + PartialEq> Clear for T {
964 fn is_clear(&self) -> bool {
965 *self == Self::clear()
966 }
967 fn clear() -> Self {
968 Default::default()
969 }
970}
971
972pub trait SimpleBitOps:
974 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{
980}
981impl<
982 T: Sized
983 + Clear
984 + core::ops::BitOr<Self, Output = Self>
985 + core::ops::BitXor<Self, Output = Self>
986 + core::ops::BitAnd<Self, Output = Self>,
987 > SimpleBitOps for T
988{
989}
990
991pub trait Hash:
995 'static
996 + MaybeSerializeDeserialize
997 + Debug
998 + Clone
999 + Eq
1000 + PartialEq
1001 + Hasher<Out = <Self as Hash>::Output>
1002{
1003 type Output: HashOutput;
1005
1006 fn hash(s: &[u8]) -> Self::Output {
1008 <Self as Hasher>::hash(s)
1009 }
1010
1011 fn hash_of<S: Encode>(s: &S) -> Self::Output {
1013 Encode::using_encoded(s, <Self as Hasher>::hash)
1014 }
1015
1016 fn ordered_trie_root(input: Vec<Vec<u8>>, state_version: StateVersion) -> Self::Output;
1018
1019 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, state_version: StateVersion) -> Self::Output;
1021}
1022
1023pub trait HashOutput:
1025 Member
1026 + MaybeSerializeDeserialize
1027 + MaybeDisplay
1028 + MaybeFromStr
1029 + Debug
1030 + core::hash::Hash
1031 + AsRef<[u8]>
1032 + AsMut<[u8]>
1033 + Copy
1034 + Ord
1035 + Default
1036 + Encode
1037 + Decode
1038 + DecodeWithMemTracking
1039 + EncodeLike
1040 + MaxEncodedLen
1041 + TypeInfo
1042{
1043}
1044
1045impl<T> HashOutput for T where
1046 T: Member
1047 + MaybeSerializeDeserialize
1048 + MaybeDisplay
1049 + MaybeFromStr
1050 + Debug
1051 + core::hash::Hash
1052 + AsRef<[u8]>
1053 + AsMut<[u8]>
1054 + Copy
1055 + Ord
1056 + Default
1057 + Encode
1058 + Decode
1059 + DecodeWithMemTracking
1060 + EncodeLike
1061 + MaxEncodedLen
1062 + TypeInfo
1063{
1064}
1065
1066#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1069pub struct BlakeTwo256;
1070
1071impl Hasher for BlakeTwo256 {
1072 type Out = sp_core::H256;
1073 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1074 const LENGTH: usize = 32;
1075
1076 fn hash(s: &[u8]) -> Self::Out {
1077 sp_io::hashing::blake2_256(s).into()
1078 }
1079}
1080
1081impl Hash for BlakeTwo256 {
1082 type Output = sp_core::H256;
1083
1084 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1085 sp_io::trie::blake2_256_ordered_root(input, version)
1086 }
1087
1088 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1089 sp_io::trie::blake2_256_root(input, version)
1090 }
1091}
1092
1093#[derive(PartialEq, Eq, Clone, Debug, TypeInfo)]
1095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1096pub struct Keccak256;
1097
1098impl Hasher for Keccak256 {
1099 type Out = sp_core::H256;
1100 type StdHasher = hash256_std_hasher::Hash256StdHasher;
1101 const LENGTH: usize = 32;
1102
1103 fn hash(s: &[u8]) -> Self::Out {
1104 sp_io::hashing::keccak_256(s).into()
1105 }
1106}
1107
1108impl Hash for Keccak256 {
1109 type Output = sp_core::H256;
1110
1111 fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
1112 sp_io::trie::keccak_256_ordered_root(input, version)
1113 }
1114
1115 fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
1116 sp_io::trie::keccak_256_root(input, version)
1117 }
1118}
1119
1120pub trait CheckEqual {
1122 fn check_equal(&self, other: &Self);
1124}
1125
1126impl CheckEqual for sp_core::H256 {
1127 #[cfg(feature = "std")]
1128 fn check_equal(&self, other: &Self) {
1129 use sp_core::hexdisplay::HexDisplay;
1130 if self != other {
1131 println!(
1132 "Hash: given={}, expected={}",
1133 HexDisplay::from(self.as_fixed_bytes()),
1134 HexDisplay::from(other.as_fixed_bytes()),
1135 );
1136 }
1137 }
1138
1139 #[cfg(not(feature = "std"))]
1140 fn check_equal(&self, other: &Self) {
1141 if self != other {
1142 "Hash not equal".print();
1143 self.as_bytes().print();
1144 other.as_bytes().print();
1145 }
1146 }
1147}
1148
1149impl CheckEqual for super::generic::DigestItem {
1150 #[cfg(feature = "std")]
1151 fn check_equal(&self, other: &Self) {
1152 if self != other {
1153 println!("DigestItem: given={:?}, expected={:?}", self, other);
1154 }
1155 }
1156
1157 #[cfg(not(feature = "std"))]
1158 fn check_equal(&self, other: &Self) {
1159 if self != other {
1160 "DigestItem not equal".print();
1161 (&Encode::encode(self)[..]).print();
1162 (&Encode::encode(other)[..]).print();
1163 }
1164 }
1165}
1166
1167sp_core::impl_maybe_marker!(
1168 trait MaybeDisplay: Display;
1170
1171 trait MaybeFromStr: FromStr;
1173
1174 trait MaybeHash: core::hash::Hash;
1176);
1177
1178sp_core::impl_maybe_marker_std_or_serde!(
1179 trait MaybeSerialize: Serialize;
1181
1182 trait MaybeSerializeDeserialize: DeserializeOwned, Serialize;
1184);
1185
1186pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {}
1188impl<T: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static> Member for T {}
1189
1190pub trait IsMember<MemberId> {
1192 fn is_member(member_id: &MemberId) -> bool;
1194}
1195
1196pub trait BlockNumber:
1198 Member
1199 + MaybeSerializeDeserialize
1200 + MaybeFromStr
1201 + Debug
1202 + core::hash::Hash
1203 + Copy
1204 + MaybeDisplay
1205 + AtLeast32BitUnsigned
1206 + Into<U256>
1207 + TryFrom<U256>
1208 + Default
1209 + TypeInfo
1210 + MaxEncodedLen
1211 + FullCodec
1212 + DecodeWithMemTracking
1213 + HasCompact<Type: DecodeWithMemTracking>
1214{
1215}
1216
1217impl<
1218 T: Member
1219 + MaybeSerializeDeserialize
1220 + MaybeFromStr
1221 + Debug
1222 + core::hash::Hash
1223 + Copy
1224 + MaybeDisplay
1225 + AtLeast32BitUnsigned
1226 + Into<U256>
1227 + TryFrom<U256>
1228 + Default
1229 + TypeInfo
1230 + MaxEncodedLen
1231 + FullCodec
1232 + DecodeWithMemTracking
1233 + HasCompact<Type: DecodeWithMemTracking>,
1234 > BlockNumber for T
1235{
1236}
1237
1238pub trait Header:
1244 Clone
1245 + Send
1246 + Sync
1247 + Codec
1248 + DecodeWithMemTracking
1249 + Eq
1250 + MaybeSerialize
1251 + Debug
1252 + TypeInfo
1253 + 'static
1254{
1255 type Number: BlockNumber;
1257 type Hash: HashOutput;
1259 type Hashing: Hash<Output = Self::Hash>;
1261
1262 fn new(
1264 number: Self::Number,
1265 extrinsics_root: Self::Hash,
1266 state_root: Self::Hash,
1267 parent_hash: Self::Hash,
1268 digest: Digest,
1269 ) -> Self;
1270
1271 fn number(&self) -> &Self::Number;
1273 fn set_number(&mut self, number: Self::Number);
1275
1276 fn extrinsics_root(&self) -> &Self::Hash;
1278 fn set_extrinsics_root(&mut self, root: Self::Hash);
1280
1281 fn state_root(&self) -> &Self::Hash;
1283 fn set_state_root(&mut self, root: Self::Hash);
1285
1286 fn parent_hash(&self) -> &Self::Hash;
1288 fn set_parent_hash(&mut self, hash: Self::Hash);
1290
1291 fn digest(&self) -> &Digest;
1293 fn digest_mut(&mut self) -> &mut Digest;
1295
1296 fn hash(&self) -> Self::Hash {
1298 <Self::Hashing as Hash>::hash_of(self)
1299 }
1300}
1301
1302#[doc(hidden)]
1322pub trait HeaderProvider {
1323 type HeaderT: Header;
1325}
1326
1327pub trait LazyExtrinsic: Sized {
1329 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error>;
1337}
1338
1339pub trait LazyBlock: Debug + Encode + Decode + Sized {
1341 type Extrinsic: LazyExtrinsic;
1343 type Header: Header;
1345
1346 fn header(&self) -> &Self::Header;
1348
1349 fn header_mut(&mut self) -> &mut Self::Header;
1351
1352 fn extrinsics(&self) -> impl Iterator<Item = Result<Self::Extrinsic, codec::Error>>;
1356}
1357
1358pub trait Block:
1363 HeaderProvider<HeaderT = Self::Header>
1364 + Into<Self::LazyBlock>
1365 + EncodeLike<Self::LazyBlock>
1366 + Clone
1367 + Send
1368 + Sync
1369 + Codec
1370 + DecodeWithMemTracking
1371 + Eq
1372 + MaybeSerialize
1373 + Debug
1374 + 'static
1375{
1376 type Extrinsic: Member + Codec + ExtrinsicLike + MaybeSerialize + Into<OpaqueExtrinsic>;
1378 type Header: Header<Hash = Self::Hash> + MaybeSerializeDeserialize;
1380 type Hash: HashOutput;
1382
1383 type LazyBlock: LazyBlock<Extrinsic = Self::Extrinsic, Header = Self::Header> + EncodeLike<Self>;
1386
1387 fn header(&self) -> &Self::Header;
1389 fn extrinsics(&self) -> &[Self::Extrinsic];
1391 fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>);
1393 fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self;
1395 fn hash(&self) -> Self::Hash {
1397 <<Self::Header as Header>::Hashing as Hash>::hash_of(self.header())
1398 }
1399}
1400
1401#[deprecated = "Use `ExtrinsicLike` along with the `CreateTransaction` trait family instead"]
1403pub trait Extrinsic: Sized {
1404 type Call: TypeInfo;
1406
1407 type SignaturePayload: SignaturePayload;
1413
1414 fn is_signed(&self) -> Option<bool> {
1417 None
1418 }
1419
1420 fn is_bare(&self) -> bool {
1422 !self.is_signed().unwrap_or(true)
1423 }
1424
1425 fn new(_call: Self::Call, _signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
1428 None
1429 }
1430}
1431
1432pub trait ExtrinsicLike: Sized {
1434 #[deprecated = "Use and implement `!is_bare()` instead"]
1437 fn is_signed(&self) -> Option<bool> {
1438 None
1439 }
1440
1441 fn is_bare(&self) -> bool {
1443 #[allow(deprecated)]
1444 !self.is_signed().unwrap_or(true)
1445 }
1446}
1447
1448#[allow(deprecated)]
1449impl<T> ExtrinsicLike for T
1450where
1451 T: Extrinsic,
1452{
1453 fn is_signed(&self) -> Option<bool> {
1454 #[allow(deprecated)]
1455 <Self as Extrinsic>::is_signed(&self)
1456 }
1457
1458 fn is_bare(&self) -> bool {
1459 <Self as Extrinsic>::is_bare(&self)
1460 }
1461}
1462
1463pub trait ExtrinsicCall: ExtrinsicLike {
1465 type Call;
1467
1468 fn call(&self) -> &Self::Call;
1470
1471 fn into_call(self) -> Self::Call;
1473}
1474
1475pub trait SignaturePayload {
1478 type SignatureAddress: TypeInfo;
1482
1483 type Signature: TypeInfo;
1487
1488 type SignatureExtra: TypeInfo;
1492}
1493
1494impl SignaturePayload for () {
1495 type SignatureAddress = ();
1496 type Signature = ();
1497 type SignatureExtra = ();
1498}
1499
1500pub trait ExtrinsicMetadata {
1502 const VERSIONS: &'static [u8];
1506
1507 type TransactionExtensionPipelines;
1514}
1515
1516pub type HashingFor<B> = <<B as Block>::Header as Header>::Hashing;
1518pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
1520pub trait Checkable<Context>: Sized {
1527 type Checked;
1529
1530 fn check(self, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
1532
1533 #[cfg(feature = "try-runtime")]
1542 fn unchecked_into_checked_i_know_what_i_am_doing(
1543 self,
1544 c: &Context,
1545 ) -> Result<Self::Checked, TransactionValidityError>;
1546}
1547
1548pub trait BlindCheckable: Sized {
1553 type Checked;
1555
1556 fn check(self) -> Result<Self::Checked, TransactionValidityError>;
1558}
1559
1560impl<T: BlindCheckable, Context> Checkable<Context> for T {
1562 type Checked = <Self as BlindCheckable>::Checked;
1563
1564 fn check(self, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
1565 BlindCheckable::check(self)
1566 }
1567
1568 #[cfg(feature = "try-runtime")]
1569 fn unchecked_into_checked_i_know_what_i_am_doing(
1570 self,
1571 _: &Context,
1572 ) -> Result<Self::Checked, TransactionValidityError> {
1573 unreachable!();
1574 }
1575}
1576
1577pub trait RefundWeight {
1579 fn refund(&mut self, weight: sp_weights::Weight);
1581}
1582
1583pub trait ExtensionPostDispatchWeightHandler<DispatchInfo>: RefundWeight {
1586 fn set_extension_weight(&mut self, info: &DispatchInfo);
1588}
1589
1590impl RefundWeight for () {
1591 fn refund(&mut self, _weight: sp_weights::Weight) {}
1592}
1593
1594impl ExtensionPostDispatchWeightHandler<()> for () {
1595 fn set_extension_weight(&mut self, _info: &()) {}
1596}
1597
1598pub trait Dispatchable {
1601 type RuntimeOrigin: Debug;
1605 type Config;
1607 type Info;
1611 type PostInfo: Eq
1614 + PartialEq
1615 + Clone
1616 + Copy
1617 + Encode
1618 + Decode
1619 + Printable
1620 + ExtensionPostDispatchWeightHandler<Self::Info>;
1621 fn dispatch(self, origin: Self::RuntimeOrigin)
1623 -> crate::DispatchResultWithInfo<Self::PostInfo>;
1624}
1625
1626pub type DispatchOriginOf<T> = <T as Dispatchable>::RuntimeOrigin;
1628pub type DispatchInfoOf<T> = <T as Dispatchable>::Info;
1630pub type PostDispatchInfoOf<T> = <T as Dispatchable>::PostInfo;
1632
1633impl Dispatchable for () {
1634 type RuntimeOrigin = ();
1635 type Config = ();
1636 type Info = ();
1637 type PostInfo = ();
1638 fn dispatch(
1639 self,
1640 _origin: Self::RuntimeOrigin,
1641 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1642 panic!("This implementation should not be used for actual dispatch.");
1643 }
1644}
1645
1646#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
1648pub struct FakeDispatchable<Inner>(pub Inner);
1649impl<Inner> From<Inner> for FakeDispatchable<Inner> {
1650 fn from(inner: Inner) -> Self {
1651 Self(inner)
1652 }
1653}
1654impl<Inner> FakeDispatchable<Inner> {
1655 pub fn deconstruct(self) -> Inner {
1657 self.0
1658 }
1659}
1660impl<Inner> AsRef<Inner> for FakeDispatchable<Inner> {
1661 fn as_ref(&self) -> &Inner {
1662 &self.0
1663 }
1664}
1665
1666impl<Inner> Dispatchable for FakeDispatchable<Inner> {
1667 type RuntimeOrigin = ();
1668 type Config = ();
1669 type Info = ();
1670 type PostInfo = ();
1671 fn dispatch(
1672 self,
1673 _origin: Self::RuntimeOrigin,
1674 ) -> crate::DispatchResultWithInfo<Self::PostInfo> {
1675 panic!("This implementation should not be used for actual dispatch.");
1676 }
1677}
1678
1679pub trait AsSystemOriginSigner<AccountId> {
1681 fn as_system_origin_signer(&self) -> Option<&AccountId>;
1684}
1685
1686pub trait AsTransactionAuthorizedOrigin {
1700 fn is_transaction_authorized(&self) -> bool;
1710}
1711
1712#[deprecated = "Use `TransactionExtension` instead."]
1715pub trait SignedExtension:
1716 Codec + DecodeWithMemTracking + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
1717{
1718 const IDENTIFIER: &'static str;
1723
1724 type AccountId;
1726
1727 type Call: Dispatchable;
1729
1730 type AdditionalSigned: Codec + TypeInfo;
1733
1734 type Pre;
1736
1737 fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError>;
1740
1741 fn validate(
1751 &self,
1752 _who: &Self::AccountId,
1753 _call: &Self::Call,
1754 _info: &DispatchInfoOf<Self::Call>,
1755 _len: usize,
1756 ) -> TransactionValidity {
1757 Ok(ValidTransaction::default())
1758 }
1759
1760 fn pre_dispatch(
1764 self,
1765 who: &Self::AccountId,
1766 call: &Self::Call,
1767 info: &DispatchInfoOf<Self::Call>,
1768 len: usize,
1769 ) -> Result<Self::Pre, TransactionValidityError>;
1770
1771 fn post_dispatch(
1788 _pre: Option<Self::Pre>,
1789 _info: &DispatchInfoOf<Self::Call>,
1790 _post_info: &PostDispatchInfoOf<Self::Call>,
1791 _len: usize,
1792 _result: &DispatchResult,
1793 ) -> Result<(), TransactionValidityError> {
1794 Ok(())
1795 }
1796
1797 fn metadata() -> Vec<TransactionExtensionMetadata> {
1806 alloc::vec![TransactionExtensionMetadata {
1807 identifier: Self::IDENTIFIER,
1808 ty: scale_info::meta_type::<Self>(),
1809 implicit: scale_info::meta_type::<Self::AdditionalSigned>()
1810 }]
1811 }
1812
1813 fn validate_unsigned(
1820 _call: &Self::Call,
1821 _info: &DispatchInfoOf<Self::Call>,
1822 _len: usize,
1823 ) -> TransactionValidity {
1824 Ok(ValidTransaction::default())
1825 }
1826
1827 fn pre_dispatch_unsigned(
1836 call: &Self::Call,
1837 info: &DispatchInfoOf<Self::Call>,
1838 len: usize,
1839 ) -> Result<(), TransactionValidityError> {
1840 Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into)
1841 }
1842}
1843
1844pub trait Applyable: Sized + Send + Sync {
1860 type Call: Dispatchable;
1862
1863 #[allow(deprecated)]
1868 fn validate<V: ValidateUnsigned<Call = Self::Call>>(
1869 &self,
1870 source: TransactionSource,
1871 info: &DispatchInfoOf<Self::Call>,
1872 len: usize,
1873 ) -> TransactionValidity;
1874
1875 #[allow(deprecated)]
1881 fn apply<V: ValidateUnsigned<Call = Self::Call>>(
1882 self,
1883 info: &DispatchInfoOf<Self::Call>,
1884 len: usize,
1885 ) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>>;
1886}
1887
1888pub trait GetRuntimeBlockType {
1890 type RuntimeBlock: self::Block;
1892}
1893
1894pub trait GetNodeBlockType {
1896 type NodeBlock: self::Block;
1898}
1899
1900#[deprecated(
1915 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"
1916)]
1917pub trait ValidateUnsigned {
1918 type Call;
1920
1921 fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
1934 Self::validate_unsigned(TransactionSource::InBlock, call)
1935 .map(|_| ())
1936 .map_err(Into::into)
1937 }
1938
1939 fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity;
1952}
1953
1954pub trait OpaqueKeys: Clone {
1957 type KeyTypeIdProviders;
1961
1962 fn key_ids() -> &'static [KeyTypeId];
1964
1965 fn get_raw(&self, i: KeyTypeId) -> &[u8];
1967
1968 fn get<T: Decode>(&self, i: KeyTypeId) -> Option<T> {
1970 T::decode(&mut self.get_raw(i)).ok()
1971 }
1972
1973 #[must_use]
1975 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool;
1976}
1977
1978pub struct AppendZerosInput<'a, T>(&'a mut T);
1983
1984impl<'a, T> AppendZerosInput<'a, T> {
1985 pub fn new(input: &'a mut T) -> Self {
1987 Self(input)
1988 }
1989}
1990
1991impl<'a, T: codec::Input> codec::Input for AppendZerosInput<'a, T> {
1992 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
1993 Ok(None)
1994 }
1995
1996 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
1997 let remaining = self.0.remaining_len()?;
1998 let completed = if let Some(n) = remaining {
1999 let readable = into.len().min(n);
2000 self.0.read(&mut into[..readable])?;
2002 readable
2003 } else {
2004 let mut i = 0;
2006 while i < into.len() {
2007 if let Ok(b) = self.0.read_byte() {
2008 into[i] = b;
2009 i += 1;
2010 } else {
2011 break;
2012 }
2013 }
2014 i
2015 };
2016 for i in &mut into[completed..] {
2018 *i = 0;
2019 }
2020 Ok(())
2021 }
2022}
2023
2024pub struct TrailingZeroInput<'a>(&'a [u8]);
2026
2027impl<'a> TrailingZeroInput<'a> {
2028 pub fn new(data: &'a [u8]) -> Self {
2030 Self(data)
2031 }
2032
2033 pub fn zeroes() -> Self {
2035 Self::new(&[][..])
2036 }
2037}
2038
2039impl<'a> codec::Input for TrailingZeroInput<'a> {
2040 fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
2041 Ok(None)
2042 }
2043
2044 fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
2045 let len_from_inner = into.len().min(self.0.len());
2046 into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]);
2047 for i in &mut into[len_from_inner..] {
2048 *i = 0;
2049 }
2050 self.0 = &self.0[len_from_inner..];
2051
2052 Ok(())
2053 }
2054}
2055
2056pub trait AccountIdConversion<AccountId>: Sized {
2058 fn into_account_truncating(&self) -> AccountId {
2061 self.into_sub_account_truncating(&())
2062 }
2063
2064 fn try_into_account(&self) -> Option<AccountId> {
2067 self.try_into_sub_account(&())
2068 }
2069
2070 fn try_from_account(a: &AccountId) -> Option<Self> {
2072 Self::try_from_sub_account::<()>(a).map(|x| x.0)
2073 }
2074
2075 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> AccountId;
2089
2090 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<AccountId>;
2094
2095 fn try_from_sub_account<S: Decode>(x: &AccountId) -> Option<(Self, S)>;
2097}
2098
2099impl<T: Encode + Decode, Id: Encode + Decode + TypeId> AccountIdConversion<T> for Id {
2102 fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> T {
2106 (Id::TYPE_ID, self, sub)
2107 .using_encoded(|b| T::decode(&mut TrailingZeroInput(b)))
2108 .expect("All byte sequences are valid `AccountIds`; qed")
2109 }
2110
2111 fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<T> {
2113 let encoded_seed = (Id::TYPE_ID, self, sub).encode();
2114 let account = T::decode(&mut TrailingZeroInput(&encoded_seed))
2115 .expect("All byte sequences are valid `AccountIds`; qed");
2116 if encoded_seed.len() <= account.encoded_size() {
2119 Some(account)
2120 } else {
2121 None
2122 }
2123 }
2124
2125 fn try_from_sub_account<S: Decode>(x: &T) -> Option<(Self, S)> {
2126 x.using_encoded(|d| {
2127 if d[0..4] != Id::TYPE_ID {
2128 return None;
2129 }
2130 let mut cursor = &d[4..];
2131 let result = Decode::decode(&mut cursor).ok()?;
2132 if cursor.iter().all(|x| *x == 0) {
2133 Some(result)
2134 } else {
2135 None
2136 }
2137 })
2138 }
2139}
2140
2141#[macro_export]
2148macro_rules! count {
2149 ($f:ident ($($x:tt)*) ) => ();
2150 ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); };
2151 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); };
2152 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); };
2153 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => {
2154 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3);
2155 };
2156 ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => {
2157 $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4);
2158 };
2159}
2160
2161#[doc(hidden)]
2162#[macro_export]
2163macro_rules! impl_opaque_keys_inner {
2164 (
2165 $( #[ $attr:meta ] )*
2166 pub struct $name:ident {
2167 $(
2168 $( #[ $inner_attr:meta ] )*
2169 pub $field:ident: $type:ty,
2170 )*
2171 },
2172 $crate_path:path,
2173 ) => {
2174 $( #[ $attr ] )*
2175 #[doc = concat!("Generated by [`impl_opaque_keys!`](", stringify!($crate_path),"::impl_opaque_keys).")]
2177 #[derive(
2178 Clone, PartialEq, Eq,
2179 $crate::codec::Encode,
2180 $crate::codec::Decode,
2181 $crate::codec::DecodeWithMemTracking,
2182 $crate::scale_info::TypeInfo,
2183 Debug,
2184 )]
2185 pub struct $name {
2186 $(
2187 $( #[ $inner_attr ] )*
2188 pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public,
2189 )*
2190 }
2191
2192 impl $name {
2193 #[allow(dead_code)]
2206 pub fn generate(
2207 owner: &[u8],
2208 seed: Option<$crate::sp_std::vec::Vec<u8>>,
2209 ) -> $crate::traits::GeneratedSessionKeys<
2210 Self,
2211 (
2212 $(
2213 <
2214 <$type as $crate::BoundToRuntimeAppPublic>::Public
2215 as $crate::RuntimeAppPublic
2216 >::ProofOfPossession
2217 ),*
2218 )
2219 > {
2220 let mut keys = Self {
2221 $(
2222 $field: <
2223 <
2224 $type as $crate::BoundToRuntimeAppPublic
2225 >::Public as $crate::RuntimeAppPublic
2226 >::generate_pair(seed.clone()),
2227 )*
2228 };
2229
2230 let proof = keys.create_ownership_proof(owner)
2231 .expect("Private key that was generated a moment ago, should exist; qed");
2232
2233 $crate::traits::GeneratedSessionKeys {
2234 keys,
2235 proof
2236 }
2237 }
2238
2239 #[allow(dead_code)]
2241 pub fn into_raw_public_keys(
2242 self,
2243 ) -> $crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)> {
2244 let mut keys = Vec::new();
2245 $(
2246 keys.push((
2247 $crate::RuntimeAppPublic::to_raw_vec(&self.$field),
2248 <
2249 <
2250 $type as $crate::BoundToRuntimeAppPublic
2251 >::Public as $crate::RuntimeAppPublic
2252 >::ID,
2253 ));
2254 )*
2255
2256 keys
2257 }
2258
2259 #[allow(dead_code)]
2264 pub fn decode_into_raw_public_keys(
2265 encoded: &[u8],
2266 ) -> Option<$crate::Vec<($crate::Vec<u8>, $crate::KeyTypeId)>> {
2267 <Self as $crate::codec::Decode>::decode(&mut &encoded[..])
2268 .ok()
2269 .map(|s| s.into_raw_public_keys())
2270 }
2271
2272 #[allow(dead_code)]
2282 pub fn create_ownership_proof(
2283 &mut self,
2284 owner: &[u8],
2285 ) -> $crate::sp_std::result::Result<
2286 (
2287 $(
2288 <
2289 <$type as $crate::BoundToRuntimeAppPublic>::Public
2290 as $crate::RuntimeAppPublic
2291 >::ProofOfPossession
2292 ),*
2293 ),
2294 ()
2295 > {
2296 let res = ($(
2297 $crate::RuntimeAppPublic::generate_proof_of_possession(&mut self.$field, &owner).ok_or(())?
2298 ),*);
2299
2300 Ok(res)
2301 }
2302 }
2303
2304 impl $crate::traits::OpaqueKeys for $name {
2305 type KeyTypeIdProviders = ( $( $type, )* );
2306
2307 fn key_ids() -> &'static [$crate::KeyTypeId] {
2308 &[
2309 $(
2310 <
2311 <
2312 $type as $crate::BoundToRuntimeAppPublic
2313 >::Public as $crate::RuntimeAppPublic
2314 >::ID
2315 ),*
2316 ]
2317 }
2318
2319 fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] {
2320 match i {
2321 $(
2322 i if i == <
2323 <
2324 $type as $crate::BoundToRuntimeAppPublic
2325 >::Public as $crate::RuntimeAppPublic
2326 >::ID =>
2327 self.$field.as_ref(),
2328 )*
2329 _ => &[],
2330 }
2331 }
2332
2333 fn ownership_proof_is_valid(&self, owner: &[u8], proof: &[u8]) -> bool {
2334 let Ok(proof) = <($(
2336 <
2337 <
2338 $type as $crate::BoundToRuntimeAppPublic
2339 >::Public as $crate::RuntimeAppPublic
2340 >::ProofOfPossession
2341 ),*) as $crate::codec::DecodeAll>::decode_all(&mut &proof[..]) else {
2342 return false
2343 };
2344
2345 let ( $( $field ),* ) = proof;
2347
2348 $(
2350 let valid = $crate::RuntimeAppPublic::verify_proof_of_possession(&self.$field, &owner, &$field);
2351
2352 if !valid {
2353 return false
2355 }
2356 )*
2357
2358 true
2359 }
2360 }
2361 };
2362}
2363
2364#[derive(Debug, Clone, Encode, Decode, TypeInfo)]
2371pub struct GeneratedSessionKeys<Keys, Proof> {
2372 pub keys: Keys,
2374 pub proof: Proof,
2376}
2377
2378#[macro_export]
2408#[cfg(any(feature = "serde", feature = "std"))]
2409macro_rules! impl_opaque_keys {
2410 {
2411 $( #[ $attr:meta ] )*
2412 pub struct $name:ident {
2413 $(
2414 $( #[ $inner_attr:meta ] )*
2415 pub $field:ident: $type:ty,
2416 )*
2417 }
2418 } => {
2419 $crate::paste::paste! {
2420 use $crate::serde as [< __opaque_keys_serde_import__ $name >];
2421
2422 $crate::impl_opaque_keys_inner! {
2423 $( #[ $attr ] )*
2424 #[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
2425 #[serde(crate = "__opaque_keys_serde_import__" $name)]
2426 pub struct $name {
2427 $(
2428 $( #[ $inner_attr ] )*
2429 pub $field: $type,
2430 )*
2431 },
2432 $crate,
2433 }
2434 }
2435 }
2436}
2437
2438#[macro_export]
2439#[cfg(all(not(feature = "std"), not(feature = "serde")))]
2440#[doc(hidden)]
2441macro_rules! impl_opaque_keys {
2442 {
2443 $( #[ $attr:meta ] )*
2444 pub struct $name:ident {
2445 $(
2446 $( #[ $inner_attr:meta ] )*
2447 pub $field:ident: $type:ty,
2448 )*
2449 }
2450 } => {
2451 $crate::impl_opaque_keys_inner! {
2452 $( #[ $attr ] )*
2453 pub struct $name {
2454 $(
2455 $( #[ $inner_attr ] )*
2456 pub $field: $type,
2457 )*
2458 },
2459 $crate,
2460 }
2461 }
2462}
2463
2464pub trait Printable {
2466 fn print(&self);
2468}
2469
2470impl<T: Printable> Printable for &T {
2471 fn print(&self) {
2472 (*self).print()
2473 }
2474}
2475
2476impl Printable for u8 {
2477 fn print(&self) {
2478 (*self as u64).print()
2479 }
2480}
2481
2482impl Printable for u32 {
2483 fn print(&self) {
2484 (*self as u64).print()
2485 }
2486}
2487
2488impl Printable for usize {
2489 fn print(&self) {
2490 (*self as u64).print()
2491 }
2492}
2493
2494impl Printable for u64 {
2495 fn print(&self) {
2496 sp_io::misc::print_num(*self);
2497 }
2498}
2499
2500impl Printable for &[u8] {
2501 fn print(&self) {
2502 sp_io::misc::print_hex(self);
2503 }
2504}
2505
2506impl<const N: usize> Printable for [u8; N] {
2507 fn print(&self) {
2508 sp_io::misc::print_hex(&self[..]);
2509 }
2510}
2511
2512impl Printable for &str {
2513 fn print(&self) {
2514 sp_io::misc::print_utf8(self.as_bytes());
2515 }
2516}
2517
2518impl Printable for bool {
2519 fn print(&self) {
2520 if *self {
2521 "true".print()
2522 } else {
2523 "false".print()
2524 }
2525 }
2526}
2527
2528impl Printable for sp_weights::Weight {
2529 fn print(&self) {
2530 self.ref_time().print()
2531 }
2532}
2533
2534impl Printable for () {
2535 fn print(&self) {
2536 "()".print()
2537 }
2538}
2539
2540#[impl_for_tuples(1, 12)]
2541impl Printable for Tuple {
2542 fn print(&self) {
2543 for_tuples!( #( Tuple.print(); )* )
2544 }
2545}
2546
2547#[cfg(feature = "std")]
2549pub trait BlockIdTo<Block: self::Block> {
2550 type Error: std::error::Error;
2552
2553 fn to_hash(
2555 &self,
2556 block_id: &crate::generic::BlockId<Block>,
2557 ) -> Result<Option<Block::Hash>, Self::Error>;
2558
2559 fn to_number(
2561 &self,
2562 block_id: &crate::generic::BlockId<Block>,
2563 ) -> Result<Option<NumberFor<Block>>, Self::Error>;
2564}
2565
2566pub trait BlockNumberProvider {
2568 type BlockNumber: Codec
2570 + DecodeWithMemTracking
2571 + Clone
2572 + Ord
2573 + Eq
2574 + AtLeast32BitUnsigned
2575 + TypeInfo
2576 + Debug
2577 + MaxEncodedLen
2578 + Copy
2579 + EncodeLike
2580 + Default;
2581
2582 fn current_block_number() -> Self::BlockNumber;
2598
2599 #[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
2605 fn set_block_number(_block: Self::BlockNumber) {}
2606}
2607
2608impl BlockNumberProvider for () {
2609 type BlockNumber = u32;
2610 fn current_block_number() -> Self::BlockNumber {
2611 0
2612 }
2613}
2614
2615#[cfg(test)]
2616mod tests {
2617 use super::*;
2618 use crate::codec::{Decode, Encode, Input};
2619 #[cfg(feature = "bls-experimental")]
2620 use sp_core::ecdsa_bls381;
2621 use sp_core::{
2622 crypto::{Pair, UncheckedFrom},
2623 ecdsa, ed25519,
2624 proof_of_possession::ProofOfPossessionGenerator,
2625 sr25519,
2626 };
2627 use std::sync::Arc;
2628
2629 macro_rules! signature_verify_test {
2630 ($algorithm:ident) => {
2631 let msg = &b"test-message"[..];
2632 let wrong_msg = &b"test-msg"[..];
2633 let (pair, _) = $algorithm::Pair::generate();
2634
2635 let signature = pair.sign(&msg);
2636 assert!($algorithm::Pair::verify(&signature, msg, &pair.public()));
2637
2638 assert!(signature.verify(msg, &pair.public()));
2639 assert!(!signature.verify(wrong_msg, &pair.public()));
2640 };
2641 }
2642
2643 mod t {
2644 use sp_application_crypto::{app_crypto, sr25519};
2645 use sp_core::crypto::KeyTypeId;
2646 app_crypto!(sr25519, KeyTypeId(*b"test"));
2647 }
2648
2649 #[test]
2650 fn app_verify_works() {
2651 use super::AppVerify;
2652 use t::*;
2653
2654 let s = Signature::try_from(vec![0; 64]).unwrap();
2655 let _ = s.verify(&[0u8; 100][..], &Public::unchecked_from([0; 32]));
2656 }
2657
2658 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2659 struct U128Value(u128);
2660 impl super::TypeId for U128Value {
2661 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0x0d, 0xf0];
2662 }
2663 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2666 struct U32Value(u32);
2667 impl super::TypeId for U32Value {
2668 const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
2669 }
2670 #[derive(Encode, Decode, Default, PartialEq, Debug)]
2673 struct U16Value(u16);
2674 impl super::TypeId for U16Value {
2675 const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
2676 }
2677 type AccountId = u64;
2680
2681 #[test]
2682 fn into_account_truncating_should_work() {
2683 let r: AccountId = U32Value::into_account_truncating(&U32Value(0xdeadbeef));
2684 assert_eq!(r, 0x_deadbeef_cafef00d);
2685 }
2686
2687 #[test]
2688 fn try_into_account_should_work() {
2689 let r: AccountId = U32Value::try_into_account(&U32Value(0xdeadbeef)).unwrap();
2690 assert_eq!(r, 0x_deadbeef_cafef00d);
2691
2692 let maybe: Option<AccountId> = U128Value::try_into_account(&U128Value(u128::MAX));
2694 assert!(maybe.is_none());
2695 }
2696
2697 #[test]
2698 fn try_from_account_should_work() {
2699 let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
2700 assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
2701 }
2702
2703 #[test]
2704 fn into_account_truncating_with_fill_should_work() {
2705 let r: AccountId = U16Value::into_account_truncating(&U16Value(0xc0da));
2706 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2707 }
2708
2709 #[test]
2710 fn try_into_sub_account_should_work() {
2711 let r: AccountId = U16Value::try_into_account(&U16Value(0xc0da)).unwrap();
2712 assert_eq!(r, 0x_0000_c0da_f00dcafe);
2713
2714 let maybe: Option<AccountId> = U16Value::try_into_sub_account(
2715 &U16Value(0xc0da),
2716 "a really large amount of additional encoded information which will certainly overflow the account id type ;)"
2717 );
2718
2719 assert!(maybe.is_none())
2720 }
2721
2722 #[test]
2723 fn try_from_account_with_fill_should_work() {
2724 let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
2725 assert_eq!(r.unwrap(), U16Value(0xc0da));
2726 }
2727
2728 #[test]
2729 fn bad_try_from_account_should_fail() {
2730 let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
2731 assert!(r.is_none());
2732 let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
2733 assert!(r.is_none());
2734 }
2735
2736 #[test]
2737 fn trailing_zero_should_work() {
2738 let mut t = super::TrailingZeroInput(&[1, 2, 3]);
2739 assert_eq!(t.remaining_len(), Ok(None));
2740 let mut buffer = [0u8; 2];
2741 assert_eq!(t.read(&mut buffer), Ok(()));
2742 assert_eq!(t.remaining_len(), Ok(None));
2743 assert_eq!(buffer, [1, 2]);
2744 assert_eq!(t.read(&mut buffer), Ok(()));
2745 assert_eq!(t.remaining_len(), Ok(None));
2746 assert_eq!(buffer, [3, 0]);
2747 assert_eq!(t.read(&mut buffer), Ok(()));
2748 assert_eq!(t.remaining_len(), Ok(None));
2749 assert_eq!(buffer, [0, 0]);
2750 }
2751
2752 #[test]
2753 fn ed25519_verify_works() {
2754 signature_verify_test!(ed25519);
2755 }
2756
2757 #[test]
2758 fn sr25519_verify_works() {
2759 signature_verify_test!(sr25519);
2760 }
2761
2762 #[test]
2763 fn ecdsa_verify_works() {
2764 signature_verify_test!(ecdsa);
2765
2766 let msg = &b"test-message"[..];
2767 let (pair, _) = ecdsa::Pair::generate();
2768 let signature = pair.sign(msg);
2769 let high_s_signature =
2770 ecdsa::Signature::from_raw(crate::tests::make_high_s_signature(signature.as_ref()));
2771 assert!(!high_s_signature.verify(msg, &pair.public()));
2772 }
2773
2774 #[test]
2775 #[cfg(feature = "bls-experimental")]
2776 fn ecdsa_bls381_verify_works() {
2777 signature_verify_test!(ecdsa_bls381);
2778 }
2779
2780 pub struct Sr25519Key;
2781 impl crate::BoundToRuntimeAppPublic for Sr25519Key {
2782 type Public = sp_application_crypto::sr25519::AppPublic;
2783 }
2784
2785 pub struct Ed25519Key;
2786 impl crate::BoundToRuntimeAppPublic for Ed25519Key {
2787 type Public = sp_application_crypto::ed25519::AppPublic;
2788 }
2789
2790 pub struct EcdsaKey;
2791 impl crate::BoundToRuntimeAppPublic for EcdsaKey {
2792 type Public = sp_application_crypto::ecdsa::AppPublic;
2793 }
2794
2795 impl_opaque_keys! {
2796 pub struct SessionKeys {
2798 pub sr25519: Sr25519Key,
2799 pub ed25519: Ed25519Key,
2800 pub ecdsa: EcdsaKey,
2801 }
2802 }
2803
2804 #[test]
2805 fn opaque_keys_ownership_proof_works() {
2806 let mut sr25519 = sp_core::sr25519::Pair::generate().0;
2807 let mut ed25519 = sp_core::ed25519::Pair::generate().0;
2808 let mut ecdsa = sp_core::ecdsa::Pair::generate().0;
2809
2810 let session_keys = SessionKeys {
2811 sr25519: sr25519.public().into(),
2812 ed25519: ed25519.public().into(),
2813 ecdsa: ecdsa.public().into(),
2814 };
2815
2816 let owner = &b"owner"[..];
2817
2818 let sr25519_sig = sr25519.generate_proof_of_possession(&owner);
2819 let ed25519_sig = ed25519.generate_proof_of_possession(&owner);
2820 let ecdsa_sig = ecdsa.generate_proof_of_possession(&owner);
2821
2822 for invalidate in [None, Some(0), Some(1), Some(2)] {
2823 let proof = if let Some(invalidate) = invalidate {
2824 match invalidate {
2825 0 => (
2826 sr25519.generate_proof_of_possession(&b"invalid"[..]),
2827 &ed25519_sig,
2828 &ecdsa_sig,
2829 )
2830 .encode(),
2831 1 => (
2832 &sr25519_sig,
2833 ed25519.generate_proof_of_possession(&b"invalid"[..]),
2834 &ecdsa_sig,
2835 )
2836 .encode(),
2837 2 => (
2838 &sr25519_sig,
2839 &ed25519_sig,
2840 ecdsa.generate_proof_of_possession(&b"invalid"[..]),
2841 )
2842 .encode(),
2843 _ => unreachable!(),
2844 }
2845 } else {
2846 (&sr25519_sig, &ed25519_sig, &ecdsa_sig).encode()
2847 };
2848
2849 assert_eq!(session_keys.ownership_proof_is_valid(owner, &proof), invalidate.is_none());
2850 }
2851
2852 let proof = (&sr25519_sig, &ed25519_sig, &ecdsa_sig, "hello").encode();
2854 assert!(!session_keys.ownership_proof_is_valid(owner, &proof));
2855
2856 let mut ext = sp_io::TestExternalities::default();
2857 ext.register_extension(sp_keystore::KeystoreExt(Arc::new(
2858 sp_keystore::testing::MemoryKeystore::new(),
2859 )));
2860
2861 ext.execute_with(|| {
2862 let session_keys = SessionKeys::generate(&owner, None);
2863
2864 assert!(session_keys
2865 .keys
2866 .ownership_proof_is_valid(&owner, &session_keys.proof.encode()));
2867 });
2868 }
2869}