1#![warn(missing_docs)]
46#![cfg_attr(not(feature = "std"), no_std)]
47
48#[doc(hidden)]
49extern crate alloc;
50
51#[doc(hidden)]
52pub use alloc::vec::Vec;
53#[doc(hidden)]
54pub use codec;
55#[doc(hidden)]
56pub use scale_info;
57#[cfg(feature = "serde")]
58#[doc(hidden)]
59pub use serde;
60#[doc(hidden)]
61pub use sp_std;
62
63#[doc(hidden)]
64pub use paste;
65#[doc(hidden)]
66pub use sp_arithmetic::traits::Saturating;
67
68#[doc(hidden)]
69pub use sp_application_crypto as app_crypto;
70
71pub use sp_core::storage::StateVersion;
72#[cfg(feature = "std")]
73pub use sp_core::storage::{Storage, StorageChild};
74
75use sp_core::{
76 crypto::{self, ByteArray, FromEntropy},
77 ecdsa, ed25519,
78 hash::{H256, H512},
79 sr25519,
80};
81
82use alloc::vec;
83use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
84use scale_info::TypeInfo;
85
86pub mod curve;
87pub mod generic;
88pub mod legacy;
89mod multiaddress;
90pub mod offchain;
91pub mod proving_trie;
92pub mod runtime_logger;
93#[cfg(feature = "std")]
94pub mod testing;
95pub mod traits;
96pub mod transaction_validity;
97pub mod type_with_default;
98
99pub use multiaddress::MultiAddress;
101
102use proving_trie::TrieError;
103
104pub use generic::{Digest, DigestItem};
106
107pub use sp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
108pub use sp_core::{
110 bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec},
111 crypto::{key_types, AccountId32, CryptoType, CryptoTypeId, KeyTypeId},
112 TypeId,
113};
114#[cfg(feature = "std")]
116pub use sp_core::{bounded_btree_map, bounded_vec};
117
118pub use core::fmt::Debug;
120
121pub use sp_arithmetic::biguint;
123pub use sp_arithmetic::helpers_128bit;
125pub use sp_arithmetic::{
127 traits::SaturatedConversion, ArithmeticError, FixedI128, FixedI64, FixedPointNumber,
128 FixedPointOperand, FixedU128, FixedU64, InnerOf, PerThing, PerU16, Perbill, Percent, Permill,
129 Perquintill, Rational128, Rounding, UpperOf,
130};
131pub use sp_weights::Weight;
133
134pub use either::Either;
135
136pub const MAX_MODULE_ERROR_ENCODED_SIZE: usize = 4;
139
140pub type Justification = (ConsensusEngineId, EncodedJustification);
152
153pub type EncodedJustification = Vec<u8>;
155
156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
159#[derive(Default, Debug, Clone, PartialEq, Eq, Encode, Decode)]
160pub struct Justifications(Vec<Justification>);
161
162impl Justifications {
163 pub fn new(justifications: Vec<Justification>) -> Self {
165 Self(justifications)
166 }
167
168 pub fn iter(&self) -> impl Iterator<Item = &Justification> {
170 self.0.iter()
171 }
172
173 pub fn append(&mut self, justification: Justification) -> bool {
177 if self.get(justification.0).is_some() {
178 return false
179 }
180 self.0.push(justification);
181 true
182 }
183
184 pub fn get(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> {
187 self.iter().find(|j| j.0 == engine_id).map(|j| &j.1)
188 }
189
190 pub fn remove(&mut self, engine_id: ConsensusEngineId) {
192 self.0.retain(|j| j.0 != engine_id)
193 }
194
195 pub fn into_justification(self, engine_id: ConsensusEngineId) -> Option<EncodedJustification> {
198 self.into_iter().find(|j| j.0 == engine_id).map(|j| j.1)
199 }
200}
201
202impl IntoIterator for Justifications {
203 type Item = Justification;
204 type IntoIter = alloc::vec::IntoIter<Self::Item>;
205
206 fn into_iter(self) -> Self::IntoIter {
207 self.0.into_iter()
208 }
209}
210
211impl From<Justification> for Justifications {
212 fn from(justification: Justification) -> Self {
213 Self(vec![justification])
214 }
215}
216
217use traits::{Lazy, Verify};
218
219use crate::traits::{IdentifyAccount, LazyExtrinsic};
220#[cfg(feature = "serde")]
221pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
222
223#[cfg(feature = "std")]
225pub trait BuildStorage {
226 fn build_storage(&self) -> Result<sp_core::storage::Storage, String> {
228 let mut storage = Default::default();
229 self.assimilate_storage(&mut storage)?;
230 Ok(storage)
231 }
232 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String>;
234}
235
236#[cfg(feature = "std")]
238#[deprecated(
239 note = "`BuildModuleGenesisStorage` is planned to be removed in December 2023. Use `BuildStorage` instead of it."
240)]
241pub trait BuildModuleGenesisStorage<T, I>: Sized {
242 fn build_module_genesis_storage(
244 &self,
245 storage: &mut sp_core::storage::Storage,
246 ) -> Result<(), String>;
247}
248
249#[cfg(feature = "std")]
250impl BuildStorage for sp_core::storage::Storage {
251 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String> {
252 storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone())));
253 for (k, other_map) in self.children_default.iter() {
254 let k = k.clone();
255 if let Some(map) = storage.children_default.get_mut(&k) {
256 map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone())));
257 if !map.child_info.try_update(&other_map.child_info) {
258 return Err("Incompatible child info update".to_string())
259 }
260 } else {
261 storage.children_default.insert(k, other_map.clone());
262 }
263 }
264 Ok(())
265 }
266}
267
268#[cfg(feature = "std")]
269impl BuildStorage for () {
270 fn assimilate_storage(&self, _: &mut sp_core::storage::Storage) -> Result<(), String> {
271 Err("`assimilate_storage` not implemented for `()`".into())
272 }
273}
274
275pub type ConsensusEngineId = [u8; 4];
277
278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
280#[derive(
281 Eq, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, Debug, TypeInfo,
282)]
283pub enum MultiSignature {
284 Ed25519(ed25519::Signature),
286 Sr25519(sr25519::Signature),
288 Ecdsa(ecdsa::Signature),
290 Eth(ecdsa::KeccakSignature),
292}
293
294impl From<ed25519::Signature> for MultiSignature {
295 fn from(x: ed25519::Signature) -> Self {
296 Self::Ed25519(x)
297 }
298}
299
300impl TryFrom<MultiSignature> for ed25519::Signature {
301 type Error = ();
302 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
303 if let MultiSignature::Ed25519(x) = m {
304 Ok(x)
305 } else {
306 Err(())
307 }
308 }
309}
310
311impl From<sr25519::Signature> for MultiSignature {
312 fn from(x: sr25519::Signature) -> Self {
313 Self::Sr25519(x)
314 }
315}
316
317impl TryFrom<MultiSignature> for sr25519::Signature {
318 type Error = ();
319 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
320 if let MultiSignature::Sr25519(x) = m {
321 Ok(x)
322 } else {
323 Err(())
324 }
325 }
326}
327
328impl From<ecdsa::Signature> for MultiSignature {
329 fn from(x: ecdsa::Signature) -> Self {
330 Self::Ecdsa(x)
331 }
332}
333
334impl TryFrom<MultiSignature> for ecdsa::Signature {
335 type Error = ();
336 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
337 if let MultiSignature::Ecdsa(x) = m {
338 Ok(x)
339 } else {
340 Err(())
341 }
342 }
343}
344
345#[derive(
347 Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo,
348)]
349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
350pub enum MultiSigner {
351 Ed25519(ed25519::Public),
353 Sr25519(sr25519::Public),
355 Ecdsa(ecdsa::Public),
357 Eth(ecdsa::KeccakPublic),
364}
365
366impl FromEntropy for MultiSigner {
367 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
368 Ok(match input.read_byte()? % 4 {
369 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
370 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
371 2 => Self::Ecdsa(FromEntropy::from_entropy(input)?),
372 3.. => Self::Eth(FromEntropy::from_entropy(input)?),
373 })
374 }
375}
376
377impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
380 fn unchecked_from(x: T) -> Self {
381 ed25519::Public::unchecked_from(x.into()).into()
382 }
383}
384
385impl AsRef<[u8]> for MultiSigner {
386 fn as_ref(&self) -> &[u8] {
387 match *self {
388 Self::Ed25519(ref who) => who.as_ref(),
389 Self::Sr25519(ref who) => who.as_ref(),
390 Self::Ecdsa(ref who) => who.as_ref(),
391 Self::Eth(ref who) => who.as_ref(),
392 }
393 }
394}
395
396impl traits::IdentifyAccount for MultiSigner {
397 type AccountId = AccountId32;
398 fn into_account(self) -> AccountId32 {
399 match self {
400 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
401 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
402 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
403 Self::Eth(who) => {
404 let eth_address = &sp_io::hashing::keccak_256(who.as_ref())[12..];
408 let mut address = [0xEE; 32];
411 address[..20].copy_from_slice(eth_address);
412 address.into()
413 },
414 }
415 }
416}
417
418impl From<ed25519::Public> for MultiSigner {
419 fn from(x: ed25519::Public) -> Self {
420 Self::Ed25519(x)
421 }
422}
423
424impl TryFrom<MultiSigner> for ed25519::Public {
425 type Error = ();
426 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
427 if let MultiSigner::Ed25519(x) = m {
428 Ok(x)
429 } else {
430 Err(())
431 }
432 }
433}
434
435impl From<sr25519::Public> for MultiSigner {
436 fn from(x: sr25519::Public) -> Self {
437 Self::Sr25519(x)
438 }
439}
440
441impl TryFrom<MultiSigner> for sr25519::Public {
442 type Error = ();
443 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
444 if let MultiSigner::Sr25519(x) = m {
445 Ok(x)
446 } else {
447 Err(())
448 }
449 }
450}
451
452impl From<ecdsa::Public> for MultiSigner {
453 fn from(x: ecdsa::Public) -> Self {
454 Self::Ecdsa(x)
455 }
456}
457
458impl TryFrom<MultiSigner> for ecdsa::Public {
459 type Error = ();
460 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
461 if let MultiSigner::Ecdsa(x) = m {
462 Ok(x)
463 } else {
464 Err(())
465 }
466 }
467}
468
469#[cfg(feature = "std")]
470impl std::fmt::Display for MultiSigner {
471 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
472 match self {
473 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
474 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
475 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
476 Self::Eth(who) => write!(fmt, "eth: {}", who),
477 }
478 }
479}
480
481impl Verify for MultiSignature {
482 type Signer = MultiSigner;
483 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
484 let who: [u8; 32] = *signer.as_ref();
485 match self {
486 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
487 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
488 Self::Ecdsa(sig) => {
489 let m = sp_io::hashing::blake2_256(msg.get());
490 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
491 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
492 },
493 Self::Eth(sig) => {
494 let m = sp_io::hashing::keccak_256(msg.get());
495 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
496 .map_or(false, |pubkey| {
497 &MultiSigner::Eth(pubkey.into()).into_account() == signer
498 })
499 },
500 }
501 }
502}
503
504#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, Debug, TypeInfo)]
506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
507pub struct AnySignature(H512);
508
509impl Verify for AnySignature {
510 type Signer = sr25519::Public;
511 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
512 let msg = msg.get();
513 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
514 .map(|s| s.verify(msg, signer))
515 .unwrap_or(false) ||
516 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
517 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
518 Err(()) => false,
519 Ok(signer) => s.verify(msg, &signer),
520 })
521 .unwrap_or(false)
522 }
523}
524
525impl From<sr25519::Signature> for AnySignature {
526 fn from(s: sr25519::Signature) -> Self {
527 Self(s.into())
528 }
529}
530
531impl From<ed25519::Signature> for AnySignature {
532 fn from(s: ed25519::Signature) -> Self {
533 Self(s.into())
534 }
535}
536
537impl From<DispatchError> for DispatchOutcome {
538 fn from(err: DispatchError) -> Self {
539 Err(err)
540 }
541}
542
543pub type DispatchResult = core::result::Result<(), DispatchError>;
547
548pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
551
552#[derive(
554 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
555)]
556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
557pub struct ModuleError {
558 pub index: u8,
560 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
562 #[codec(skip)]
564 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
565 pub message: Option<&'static str>,
566}
567
568impl PartialEq for ModuleError {
569 fn eq(&self, other: &Self) -> bool {
570 (self.index == other.index) && (self.error == other.error)
571 }
572}
573
574#[derive(
576 Eq,
577 PartialEq,
578 Clone,
579 Copy,
580 Encode,
581 Decode,
582 DecodeWithMemTracking,
583 Debug,
584 TypeInfo,
585 MaxEncodedLen,
586)]
587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
588pub enum TransactionalError {
589 LimitReached,
591 NoLayer,
593}
594
595impl From<TransactionalError> for &'static str {
596 fn from(e: TransactionalError) -> &'static str {
597 match e {
598 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
599 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
600 }
601 }
602}
603
604impl From<TransactionalError> for DispatchError {
605 fn from(e: TransactionalError) -> DispatchError {
606 Self::Transactional(e)
607 }
608}
609
610#[derive(
612 Eq,
613 Clone,
614 Copy,
615 Encode,
616 Decode,
617 DecodeWithMemTracking,
618 Debug,
619 TypeInfo,
620 PartialEq,
621 MaxEncodedLen,
622)]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624pub enum DispatchError {
625 Other(
627 #[codec(skip)]
628 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
629 &'static str,
630 ),
631 CannotLookup,
633 BadOrigin,
635 Module(ModuleError),
637 ConsumerRemaining,
639 NoProviders,
641 TooManyConsumers,
643 Token(TokenError),
645 Arithmetic(ArithmeticError),
647 Transactional(TransactionalError),
650 Exhausted,
652 Corruption,
654 Unavailable,
656 RootNotAllowed,
658 Trie(TrieError),
660}
661
662#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
665pub struct DispatchErrorWithPostInfo<Info>
666where
667 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
668{
669 pub post_info: Info,
671 pub error: DispatchError,
673}
674
675impl DispatchError {
676 pub fn stripped(self) -> Self {
678 match self {
679 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
680 DispatchError::Module(ModuleError { index, error, message: None }),
681 m => m,
682 }
683 }
684}
685
686impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
687where
688 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
689 E: Into<DispatchError>,
690{
691 fn from(error: E) -> Self {
692 Self { post_info: Default::default(), error: error.into() }
693 }
694}
695
696impl From<crate::traits::LookupError> for DispatchError {
697 fn from(_: crate::traits::LookupError) -> Self {
698 Self::CannotLookup
699 }
700}
701
702impl From<crate::traits::BadOrigin> for DispatchError {
703 fn from(_: crate::traits::BadOrigin) -> Self {
704 Self::BadOrigin
705 }
706}
707
708#[derive(
710 Eq,
711 PartialEq,
712 Clone,
713 Copy,
714 Encode,
715 Decode,
716 DecodeWithMemTracking,
717 Debug,
718 TypeInfo,
719 MaxEncodedLen,
720)]
721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
722pub enum TokenError {
723 FundsUnavailable,
725 OnlyProvider,
728 BelowMinimum,
730 CannotCreate,
732 UnknownAsset,
734 Frozen,
736 Unsupported,
738 CannotCreateHold,
740 NotExpendable,
742 Blocked,
744}
745
746impl From<TokenError> for &'static str {
747 fn from(e: TokenError) -> &'static str {
748 match e {
749 TokenError::FundsUnavailable => "Funds are unavailable",
750 TokenError::OnlyProvider => "Account that must exist would die",
751 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
752 TokenError::CannotCreate => "Account cannot be created",
753 TokenError::UnknownAsset => "The asset in question is unknown",
754 TokenError::Frozen => "Funds exist but are frozen",
755 TokenError::Unsupported => "Operation is not supported by the asset",
756 TokenError::CannotCreateHold =>
757 "Account cannot be created for recording amount on hold",
758 TokenError::NotExpendable => "Account that is desired to remain would die",
759 TokenError::Blocked => "Account cannot receive the assets",
760 }
761 }
762}
763
764impl From<TokenError> for DispatchError {
765 fn from(e: TokenError) -> DispatchError {
766 Self::Token(e)
767 }
768}
769
770impl From<ArithmeticError> for DispatchError {
771 fn from(e: ArithmeticError) -> DispatchError {
772 Self::Arithmetic(e)
773 }
774}
775
776impl From<TrieError> for DispatchError {
777 fn from(e: TrieError) -> DispatchError {
778 Self::Trie(e)
779 }
780}
781
782impl From<&'static str> for DispatchError {
783 fn from(err: &'static str) -> DispatchError {
784 Self::Other(err)
785 }
786}
787
788impl From<DispatchError> for &'static str {
789 fn from(err: DispatchError) -> &'static str {
790 use DispatchError::*;
791 match err {
792 Other(msg) => msg,
793 CannotLookup => "Cannot lookup",
794 BadOrigin => "Bad origin",
795 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
796 ConsumerRemaining => "Consumer remaining",
797 NoProviders => "No providers",
798 TooManyConsumers => "Too many consumers",
799 Token(e) => e.into(),
800 Arithmetic(e) => e.into(),
801 Transactional(e) => e.into(),
802 Exhausted => "Resources exhausted",
803 Corruption => "State corrupt",
804 Unavailable => "Resource unavailable",
805 RootNotAllowed => "Root not allowed",
806 Trie(e) => e.into(),
807 }
808 }
809}
810
811impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
812where
813 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
814{
815 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
816 err.error.into()
817 }
818}
819
820impl traits::Printable for DispatchError {
821 fn print(&self) {
822 use DispatchError::*;
823 "DispatchError".print();
824 match self {
825 Other(err) => err.print(),
826 CannotLookup => "Cannot lookup".print(),
827 BadOrigin => "Bad origin".print(),
828 Module(ModuleError { index, error, message }) => {
829 index.print();
830 error.print();
831 if let Some(msg) = message {
832 msg.print();
833 }
834 },
835 ConsumerRemaining => "Consumer remaining".print(),
836 NoProviders => "No providers".print(),
837 TooManyConsumers => "Too many consumers".print(),
838 Token(e) => {
839 "Token error: ".print();
840 <&'static str>::from(*e).print();
841 },
842 Arithmetic(e) => {
843 "Arithmetic error: ".print();
844 <&'static str>::from(*e).print();
845 },
846 Transactional(e) => {
847 "Transactional error: ".print();
848 <&'static str>::from(*e).print();
849 },
850 Exhausted => "Resources exhausted".print(),
851 Corruption => "State corrupt".print(),
852 Unavailable => "Resource unavailable".print(),
853 RootNotAllowed => "Root not allowed".print(),
854 Trie(e) => {
855 "Trie error: ".print();
856 <&'static str>::from(*e).print();
857 },
858 }
859 }
860}
861
862impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
863where
864 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
865{
866 fn print(&self) {
867 self.error.print();
868 "PostInfo: ".print();
869 self.post_info.print();
870 }
871}
872
873pub type DispatchOutcome = Result<(), DispatchError>;
883
884pub type ApplyExtrinsicResult =
903 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
904
905pub type ApplyExtrinsicResultWithInfo<T> =
907 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
908
909pub type TryRuntimeError = DispatchError;
911
912pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
915 sig: &V,
916 item: &T,
917 signer: &<V::Signer as IdentifyAccount>::AccountId,
918) -> bool {
919 struct LazyEncode<F> {
924 inner: F,
925 encoded: Option<Vec<u8>>,
926 }
927
928 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
929 fn get(&mut self) -> &[u8] {
930 self.encoded.get_or_insert_with(&self.inner).as_slice()
931 }
932 }
933
934 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
935}
936
937#[macro_export]
955#[cfg(feature = "std")]
956macro_rules! assert_eq_error_rate {
957 ($x:expr, $y:expr, $error:expr $(,)?) => {
958 assert!(
959 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
960 ($x <= $crate::Saturating::saturating_add($y, $error)),
961 "{:?} != {:?} (with error rate {:?})",
962 $x,
963 $y,
964 $error,
965 );
966 };
967}
968
969#[macro_export]
972#[cfg(feature = "std")]
973macro_rules! assert_eq_error_rate_float {
974 ($x:expr, $y:expr, $error:expr $(,)?) => {
975 assert!(
976 ($x >= $y - $error) && ($x <= $y + $error),
977 "{:?} != {:?} (with error rate {:?})",
978 $x,
979 $y,
980 $error,
981 );
982 };
983}
984
985#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
988pub struct OpaqueExtrinsic(bytes::Bytes);
989
990impl TypeInfo for OpaqueExtrinsic {
991 type Identity = Self;
992 fn type_info() -> scale_info::Type {
993 scale_info::Type::builder()
994 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
995 .composite(
996 scale_info::build::Fields::unnamed()
997 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
998 )
999 }
1000}
1001
1002impl OpaqueExtrinsic {
1003 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1005 Self::decode(&mut bytes)
1006 }
1007
1008 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
1010 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
1011 Self::try_from_encoded_extrinsic(bytes)
1012 }
1013
1014 pub fn from_blob(bytes: Vec<u8>) -> Self {
1016 Self(bytes.into())
1017 }
1018
1019 pub fn inner(&self) -> &[u8] {
1021 &self.0
1022 }
1023}
1024
1025impl LazyExtrinsic for OpaqueExtrinsic {
1026 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
1027 Ok(Self(data.to_vec().into()))
1028 }
1029}
1030
1031impl core::fmt::Debug for OpaqueExtrinsic {
1032 #[cfg(feature = "std")]
1033 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1034 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1035 }
1036
1037 #[cfg(not(feature = "std"))]
1038 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1039 Ok(())
1040 }
1041}
1042
1043#[cfg(feature = "serde")]
1044impl ::serde::Serialize for OpaqueExtrinsic {
1045 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1046 where
1047 S: ::serde::Serializer,
1048 {
1049 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1050 }
1051}
1052
1053#[cfg(feature = "serde")]
1054impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1055 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1056 where
1057 D: ::serde::Deserializer<'a>,
1058 {
1059 let r = ::sp_core::bytes::deserialize(de)?;
1060 Decode::decode(&mut &r[..])
1061 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1062 }
1063}
1064
1065impl traits::ExtrinsicLike for OpaqueExtrinsic {
1066 fn is_bare(&self) -> bool {
1067 false
1068 }
1069}
1070
1071pub fn print(print: impl traits::Printable) {
1073 print.print();
1074}
1075
1076pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1091 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1092 let mut i = 0;
1093 let mut arr = [0; N];
1094 let s = s.as_bytes();
1095 while i < s.len() {
1096 arr[i] = s[i];
1097 i += 1;
1098 }
1099 arr
1100}
1101
1102pub enum TransactionOutcome<R> {
1104 Commit(R),
1106 Rollback(R),
1108}
1109
1110impl<R> TransactionOutcome<R> {
1111 pub fn into_inner(self) -> R {
1113 match self {
1114 Self::Commit(r) => r,
1115 Self::Rollback(r) => r,
1116 }
1117 }
1118}
1119
1120#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1122pub enum ExtrinsicInclusionMode {
1123 #[default]
1125 AllExtrinsics,
1126 OnlyInherents,
1128}
1129
1130#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
1132pub struct OpaqueValue(Vec<u8>);
1133impl OpaqueValue {
1134 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1136 OpaqueValue(inner)
1137 }
1138
1139 pub fn decode<T: Decode>(&self) -> Option<T> {
1141 Decode::decode(&mut &self.0[..]).ok()
1142 }
1143}
1144
1145#[macro_export]
1148#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1149macro_rules! create_runtime_str {
1150 ( $y:expr ) => {{
1151 $crate::Cow::Borrowed($y)
1152 }};
1153}
1154#[doc(hidden)]
1156pub use alloc::borrow::Cow;
1157
1158#[deprecated = "Use String or Cow<'static, str> instead"]
1161pub type RuntimeString = alloc::string::String;
1162
1163#[cfg(test)]
1164mod tests {
1165 use crate::traits::BlakeTwo256;
1166
1167 use super::*;
1168 use codec::{Decode, Encode};
1169 use sp_core::{crypto::Pair, hex2array};
1170 use sp_io::TestExternalities;
1171 use sp_state_machine::create_proof_check_backend;
1172
1173 #[test]
1174 fn opaque_extrinsic_serialization() {
1175 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1176 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1177 }
1178
1179 #[test]
1180 fn dispatch_error_encoding() {
1181 let error = DispatchError::Module(ModuleError {
1182 index: 1,
1183 error: [2, 0, 0, 0],
1184 message: Some("error message"),
1185 });
1186 let encoded = error.encode();
1187 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1188 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1189 assert_eq!(
1190 decoded,
1191 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1192 );
1193 }
1194
1195 #[test]
1196 fn dispatch_error_equality() {
1197 use DispatchError::*;
1198
1199 let variants = vec![
1200 Other("foo"),
1201 Other("bar"),
1202 CannotLookup,
1203 BadOrigin,
1204 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1205 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1206 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1207 ConsumerRemaining,
1208 NoProviders,
1209 Token(TokenError::FundsUnavailable),
1210 Token(TokenError::OnlyProvider),
1211 Token(TokenError::BelowMinimum),
1212 Token(TokenError::CannotCreate),
1213 Token(TokenError::UnknownAsset),
1214 Token(TokenError::Frozen),
1215 Arithmetic(ArithmeticError::Overflow),
1216 Arithmetic(ArithmeticError::Underflow),
1217 Arithmetic(ArithmeticError::DivisionByZero),
1218 ];
1219 for (i, variant) in variants.iter().enumerate() {
1220 for (j, other_variant) in variants.iter().enumerate() {
1221 if i == j {
1222 assert_eq!(variant, other_variant);
1223 } else {
1224 assert_ne!(variant, other_variant);
1225 }
1226 }
1227 }
1228
1229 assert_eq!(
1231 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1232 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1233 );
1234 }
1235
1236 #[test]
1237 fn multi_signature_ecdsa_verify_works() {
1238 let msg = &b"test-message"[..];
1239 let (pair, _) = ecdsa::Pair::generate();
1240
1241 let signature = pair.sign(&msg);
1242 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1243
1244 let multi_sig = MultiSignature::from(signature);
1245 let multi_signer = MultiSigner::from(pair.public());
1246 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1247 }
1248
1249 #[test]
1250 fn multi_signature_eth_verify_works() {
1251 let msg = &b"test-message"[..];
1252 let (pair, _) = ecdsa::KeccakPair::generate();
1253
1254 let signature = pair.sign(&msg);
1255 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1256
1257 let multi_sig = MultiSignature::Eth(signature);
1258 let multi_signer = MultiSigner::Eth(pair.public());
1259 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1260 }
1261
1262 #[test]
1263 fn multi_signer_eth_address_works() {
1264 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1265 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1266 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1267 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1268
1269 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1270 assert_eq!(
1271 ecdsa,
1272 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1273 );
1274 assert_eq!(
1275 eth,
1276 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1277 );
1278 }
1279
1280 #[test]
1281 fn execute_and_generate_proof_works() {
1282 use codec::Encode;
1283 use sp_state_machine::Backend;
1284 let mut ext = TestExternalities::default();
1285
1286 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1287 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1288 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1289 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1290
1291 let pre_root = *ext.backend.root();
1292 let (_, proof) = ext.execute_and_prove(|| {
1293 sp_io::storage::get(b"a");
1294 sp_io::storage::get(b"b");
1295 sp_io::storage::get(b"v");
1296 sp_io::storage::get(b"d");
1297 });
1298
1299 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1300 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1301
1302 println!("proof size: {:?}", proof.encoded_size());
1304 println!("compact proof size: {:?}", compact_proof.encoded_size());
1305 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1306
1307 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1309 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1310
1311 let _ = ext.execute_and_prove(|| {
1312 sp_io::storage::set(b"a", &vec![1u8; 44]);
1313 });
1314
1315 ext.execute_with(|| {
1318 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1319 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1320 });
1321 }
1322}
1323
1324#[cfg(test)]
1327mod sp_core_tests {
1328 use super::*;
1329
1330 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1331 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1332
1333 #[test]
1334 #[should_panic]
1335 fn generate_feature_enabled_macro_panics() {
1336 if_test!(panic!("This should panic"));
1337 }
1338
1339 #[test]
1340 fn generate_feature_enabled_macro_works() {
1341 if_not_test!(panic!("This should not panic"));
1342 }
1343}