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 sp_core::RuntimeDebug;
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(Debug, Clone, PartialEq, Eq, Encode, Decode)]
160pub struct Justifications(Vec<Justification>);
161
162impl Justifications {
163 pub fn iter(&self) -> impl Iterator<Item = &Justification> {
165 self.0.iter()
166 }
167
168 pub fn append(&mut self, justification: Justification) -> bool {
172 if self.get(justification.0).is_some() {
173 return false
174 }
175 self.0.push(justification);
176 true
177 }
178
179 pub fn get(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> {
182 self.iter().find(|j| j.0 == engine_id).map(|j| &j.1)
183 }
184
185 pub fn remove(&mut self, engine_id: ConsensusEngineId) {
187 self.0.retain(|j| j.0 != engine_id)
188 }
189
190 pub fn into_justification(self, engine_id: ConsensusEngineId) -> Option<EncodedJustification> {
193 self.into_iter().find(|j| j.0 == engine_id).map(|j| j.1)
194 }
195}
196
197impl IntoIterator for Justifications {
198 type Item = Justification;
199 type IntoIter = alloc::vec::IntoIter<Self::Item>;
200
201 fn into_iter(self) -> Self::IntoIter {
202 self.0.into_iter()
203 }
204}
205
206impl From<Justification> for Justifications {
207 fn from(justification: Justification) -> Self {
208 Self(vec![justification])
209 }
210}
211
212use traits::{Lazy, Verify};
213
214use crate::traits::IdentifyAccount;
215#[cfg(feature = "serde")]
216pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
217
218#[cfg(feature = "std")]
220pub trait BuildStorage {
221 fn build_storage(&self) -> Result<sp_core::storage::Storage, String> {
223 let mut storage = Default::default();
224 self.assimilate_storage(&mut storage)?;
225 Ok(storage)
226 }
227 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String>;
229}
230
231#[cfg(feature = "std")]
233#[deprecated(
234 note = "`BuildModuleGenesisStorage` is planned to be removed in December 2023. Use `BuildStorage` instead of it."
235)]
236pub trait BuildModuleGenesisStorage<T, I>: Sized {
237 fn build_module_genesis_storage(
239 &self,
240 storage: &mut sp_core::storage::Storage,
241 ) -> Result<(), String>;
242}
243
244#[cfg(feature = "std")]
245impl BuildStorage for sp_core::storage::Storage {
246 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String> {
247 storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone())));
248 for (k, other_map) in self.children_default.iter() {
249 let k = k.clone();
250 if let Some(map) = storage.children_default.get_mut(&k) {
251 map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone())));
252 if !map.child_info.try_update(&other_map.child_info) {
253 return Err("Incompatible child info update".to_string())
254 }
255 } else {
256 storage.children_default.insert(k, other_map.clone());
257 }
258 }
259 Ok(())
260 }
261}
262
263#[cfg(feature = "std")]
264impl BuildStorage for () {
265 fn assimilate_storage(&self, _: &mut sp_core::storage::Storage) -> Result<(), String> {
266 Err("`assimilate_storage` not implemented for `()`".into())
267 }
268}
269
270pub type ConsensusEngineId = [u8; 4];
272
273#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
275#[derive(
276 Eq,
277 PartialEq,
278 Clone,
279 Encode,
280 Decode,
281 DecodeWithMemTracking,
282 MaxEncodedLen,
283 RuntimeDebug,
284 TypeInfo,
285)]
286pub enum MultiSignature {
287 Ed25519(ed25519::Signature),
289 Sr25519(sr25519::Signature),
291 Ecdsa(ecdsa::Signature),
293}
294
295impl From<ed25519::Signature> for MultiSignature {
296 fn from(x: ed25519::Signature) -> Self {
297 Self::Ed25519(x)
298 }
299}
300
301impl TryFrom<MultiSignature> for ed25519::Signature {
302 type Error = ();
303 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
304 if let MultiSignature::Ed25519(x) = m {
305 Ok(x)
306 } else {
307 Err(())
308 }
309 }
310}
311
312impl From<sr25519::Signature> for MultiSignature {
313 fn from(x: sr25519::Signature) -> Self {
314 Self::Sr25519(x)
315 }
316}
317
318impl TryFrom<MultiSignature> for sr25519::Signature {
319 type Error = ();
320 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
321 if let MultiSignature::Sr25519(x) = m {
322 Ok(x)
323 } else {
324 Err(())
325 }
326 }
327}
328
329impl From<ecdsa::Signature> for MultiSignature {
330 fn from(x: ecdsa::Signature) -> Self {
331 Self::Ecdsa(x)
332 }
333}
334
335impl TryFrom<MultiSignature> for ecdsa::Signature {
336 type Error = ();
337 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
338 if let MultiSignature::Ecdsa(x) = m {
339 Ok(x)
340 } else {
341 Err(())
342 }
343 }
344}
345
346#[derive(
348 Eq,
349 PartialEq,
350 Ord,
351 PartialOrd,
352 Clone,
353 Encode,
354 Decode,
355 DecodeWithMemTracking,
356 RuntimeDebug,
357 TypeInfo,
358)]
359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
360pub enum MultiSigner {
361 Ed25519(ed25519::Public),
363 Sr25519(sr25519::Public),
365 Ecdsa(ecdsa::Public),
367}
368
369impl FromEntropy for MultiSigner {
370 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
371 Ok(match input.read_byte()? % 3 {
372 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
373 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
374 2.. => Self::Ecdsa(FromEntropy::from_entropy(input)?),
375 })
376 }
377}
378
379impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
382 fn unchecked_from(x: T) -> Self {
383 ed25519::Public::unchecked_from(x.into()).into()
384 }
385}
386
387impl AsRef<[u8]> for MultiSigner {
388 fn as_ref(&self) -> &[u8] {
389 match *self {
390 Self::Ed25519(ref who) => who.as_ref(),
391 Self::Sr25519(ref who) => who.as_ref(),
392 Self::Ecdsa(ref who) => who.as_ref(),
393 }
394 }
395}
396
397impl traits::IdentifyAccount for MultiSigner {
398 type AccountId = AccountId32;
399 fn into_account(self) -> AccountId32 {
400 match self {
401 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
402 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
403 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
404 }
405 }
406}
407
408impl From<ed25519::Public> for MultiSigner {
409 fn from(x: ed25519::Public) -> Self {
410 Self::Ed25519(x)
411 }
412}
413
414impl TryFrom<MultiSigner> for ed25519::Public {
415 type Error = ();
416 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
417 if let MultiSigner::Ed25519(x) = m {
418 Ok(x)
419 } else {
420 Err(())
421 }
422 }
423}
424
425impl From<sr25519::Public> for MultiSigner {
426 fn from(x: sr25519::Public) -> Self {
427 Self::Sr25519(x)
428 }
429}
430
431impl TryFrom<MultiSigner> for sr25519::Public {
432 type Error = ();
433 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
434 if let MultiSigner::Sr25519(x) = m {
435 Ok(x)
436 } else {
437 Err(())
438 }
439 }
440}
441
442impl From<ecdsa::Public> for MultiSigner {
443 fn from(x: ecdsa::Public) -> Self {
444 Self::Ecdsa(x)
445 }
446}
447
448impl TryFrom<MultiSigner> for ecdsa::Public {
449 type Error = ();
450 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
451 if let MultiSigner::Ecdsa(x) = m {
452 Ok(x)
453 } else {
454 Err(())
455 }
456 }
457}
458
459#[cfg(feature = "std")]
460impl std::fmt::Display for MultiSigner {
461 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
462 match self {
463 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
464 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
465 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
466 }
467 }
468}
469
470impl Verify for MultiSignature {
471 type Signer = MultiSigner;
472 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
473 let who: [u8; 32] = *signer.as_ref();
474 match self {
475 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
476 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
477 Self::Ecdsa(sig) => {
478 let m = sp_io::hashing::blake2_256(msg.get());
479 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
480 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
481 },
482 }
483 }
484}
485
486#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
489pub struct AnySignature(H512);
490
491impl Verify for AnySignature {
492 type Signer = sr25519::Public;
493 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
494 let msg = msg.get();
495 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
496 .map(|s| s.verify(msg, signer))
497 .unwrap_or(false) ||
498 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
499 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
500 Err(()) => false,
501 Ok(signer) => s.verify(msg, &signer),
502 })
503 .unwrap_or(false)
504 }
505}
506
507impl From<sr25519::Signature> for AnySignature {
508 fn from(s: sr25519::Signature) -> Self {
509 Self(s.into())
510 }
511}
512
513impl From<ed25519::Signature> for AnySignature {
514 fn from(s: ed25519::Signature) -> Self {
515 Self(s.into())
516 }
517}
518
519impl From<DispatchError> for DispatchOutcome {
520 fn from(err: DispatchError) -> Self {
521 Err(err)
522 }
523}
524
525pub type DispatchResult = core::result::Result<(), DispatchError>;
529
530pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
533
534#[derive(
536 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
537)]
538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
539pub struct ModuleError {
540 pub index: u8,
542 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
544 #[codec(skip)]
546 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
547 pub message: Option<&'static str>,
548}
549
550impl PartialEq for ModuleError {
551 fn eq(&self, other: &Self) -> bool {
552 (self.index == other.index) && (self.error == other.error)
553 }
554}
555
556#[derive(
558 Eq,
559 PartialEq,
560 Clone,
561 Copy,
562 Encode,
563 Decode,
564 DecodeWithMemTracking,
565 Debug,
566 TypeInfo,
567 MaxEncodedLen,
568)]
569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
570pub enum TransactionalError {
571 LimitReached,
573 NoLayer,
575}
576
577impl From<TransactionalError> for &'static str {
578 fn from(e: TransactionalError) -> &'static str {
579 match e {
580 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
581 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
582 }
583 }
584}
585
586impl From<TransactionalError> for DispatchError {
587 fn from(e: TransactionalError) -> DispatchError {
588 Self::Transactional(e)
589 }
590}
591
592#[derive(
594 Eq,
595 Clone,
596 Copy,
597 Encode,
598 Decode,
599 DecodeWithMemTracking,
600 Debug,
601 TypeInfo,
602 PartialEq,
603 MaxEncodedLen,
604)]
605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
606pub enum DispatchError {
607 Other(
609 #[codec(skip)]
610 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
611 &'static str,
612 ),
613 CannotLookup,
615 BadOrigin,
617 Module(ModuleError),
619 ConsumerRemaining,
621 NoProviders,
623 TooManyConsumers,
625 Token(TokenError),
627 Arithmetic(ArithmeticError),
629 Transactional(TransactionalError),
632 Exhausted,
634 Corruption,
636 Unavailable,
638 RootNotAllowed,
640 Trie(TrieError),
642}
643
644#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
647pub struct DispatchErrorWithPostInfo<Info>
648where
649 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
650{
651 pub post_info: Info,
653 pub error: DispatchError,
655}
656
657impl DispatchError {
658 pub fn stripped(self) -> Self {
660 match self {
661 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
662 DispatchError::Module(ModuleError { index, error, message: None }),
663 m => m,
664 }
665 }
666}
667
668impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
669where
670 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
671 E: Into<DispatchError>,
672{
673 fn from(error: E) -> Self {
674 Self { post_info: Default::default(), error: error.into() }
675 }
676}
677
678impl From<crate::traits::LookupError> for DispatchError {
679 fn from(_: crate::traits::LookupError) -> Self {
680 Self::CannotLookup
681 }
682}
683
684impl From<crate::traits::BadOrigin> for DispatchError {
685 fn from(_: crate::traits::BadOrigin) -> Self {
686 Self::BadOrigin
687 }
688}
689
690#[derive(
692 Eq,
693 PartialEq,
694 Clone,
695 Copy,
696 Encode,
697 Decode,
698 DecodeWithMemTracking,
699 Debug,
700 TypeInfo,
701 MaxEncodedLen,
702)]
703#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
704pub enum TokenError {
705 FundsUnavailable,
707 OnlyProvider,
710 BelowMinimum,
712 CannotCreate,
714 UnknownAsset,
716 Frozen,
718 Unsupported,
720 CannotCreateHold,
722 NotExpendable,
724 Blocked,
726}
727
728impl From<TokenError> for &'static str {
729 fn from(e: TokenError) -> &'static str {
730 match e {
731 TokenError::FundsUnavailable => "Funds are unavailable",
732 TokenError::OnlyProvider => "Account that must exist would die",
733 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
734 TokenError::CannotCreate => "Account cannot be created",
735 TokenError::UnknownAsset => "The asset in question is unknown",
736 TokenError::Frozen => "Funds exist but are frozen",
737 TokenError::Unsupported => "Operation is not supported by the asset",
738 TokenError::CannotCreateHold =>
739 "Account cannot be created for recording amount on hold",
740 TokenError::NotExpendable => "Account that is desired to remain would die",
741 TokenError::Blocked => "Account cannot receive the assets",
742 }
743 }
744}
745
746impl From<TokenError> for DispatchError {
747 fn from(e: TokenError) -> DispatchError {
748 Self::Token(e)
749 }
750}
751
752impl From<ArithmeticError> for DispatchError {
753 fn from(e: ArithmeticError) -> DispatchError {
754 Self::Arithmetic(e)
755 }
756}
757
758impl From<TrieError> for DispatchError {
759 fn from(e: TrieError) -> DispatchError {
760 Self::Trie(e)
761 }
762}
763
764impl From<&'static str> for DispatchError {
765 fn from(err: &'static str) -> DispatchError {
766 Self::Other(err)
767 }
768}
769
770impl From<DispatchError> for &'static str {
771 fn from(err: DispatchError) -> &'static str {
772 use DispatchError::*;
773 match err {
774 Other(msg) => msg,
775 CannotLookup => "Cannot lookup",
776 BadOrigin => "Bad origin",
777 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
778 ConsumerRemaining => "Consumer remaining",
779 NoProviders => "No providers",
780 TooManyConsumers => "Too many consumers",
781 Token(e) => e.into(),
782 Arithmetic(e) => e.into(),
783 Transactional(e) => e.into(),
784 Exhausted => "Resources exhausted",
785 Corruption => "State corrupt",
786 Unavailable => "Resource unavailable",
787 RootNotAllowed => "Root not allowed",
788 Trie(e) => e.into(),
789 }
790 }
791}
792
793impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
794where
795 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
796{
797 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
798 err.error.into()
799 }
800}
801
802impl traits::Printable for DispatchError {
803 fn print(&self) {
804 use DispatchError::*;
805 "DispatchError".print();
806 match self {
807 Other(err) => err.print(),
808 CannotLookup => "Cannot lookup".print(),
809 BadOrigin => "Bad origin".print(),
810 Module(ModuleError { index, error, message }) => {
811 index.print();
812 error.print();
813 if let Some(msg) = message {
814 msg.print();
815 }
816 },
817 ConsumerRemaining => "Consumer remaining".print(),
818 NoProviders => "No providers".print(),
819 TooManyConsumers => "Too many consumers".print(),
820 Token(e) => {
821 "Token error: ".print();
822 <&'static str>::from(*e).print();
823 },
824 Arithmetic(e) => {
825 "Arithmetic error: ".print();
826 <&'static str>::from(*e).print();
827 },
828 Transactional(e) => {
829 "Transactional error: ".print();
830 <&'static str>::from(*e).print();
831 },
832 Exhausted => "Resources exhausted".print(),
833 Corruption => "State corrupt".print(),
834 Unavailable => "Resource unavailable".print(),
835 RootNotAllowed => "Root not allowed".print(),
836 Trie(e) => {
837 "Trie error: ".print();
838 <&'static str>::from(*e).print();
839 },
840 }
841 }
842}
843
844impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
845where
846 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
847{
848 fn print(&self) {
849 self.error.print();
850 "PostInfo: ".print();
851 self.post_info.print();
852 }
853}
854
855pub type DispatchOutcome = Result<(), DispatchError>;
865
866pub type ApplyExtrinsicResult =
885 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
886
887pub type ApplyExtrinsicResultWithInfo<T> =
889 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
890
891pub type TryRuntimeError = DispatchError;
893
894pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
897 sig: &V,
898 item: &T,
899 signer: &<V::Signer as IdentifyAccount>::AccountId,
900) -> bool {
901 struct LazyEncode<F> {
906 inner: F,
907 encoded: Option<Vec<u8>>,
908 }
909
910 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
911 fn get(&mut self) -> &[u8] {
912 self.encoded.get_or_insert_with(&self.inner).as_slice()
913 }
914 }
915
916 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
917}
918
919#[macro_export]
937#[cfg(feature = "std")]
938macro_rules! assert_eq_error_rate {
939 ($x:expr, $y:expr, $error:expr $(,)?) => {
940 assert!(
941 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
942 ($x <= $crate::Saturating::saturating_add($y, $error)),
943 "{:?} != {:?} (with error rate {:?})",
944 $x,
945 $y,
946 $error,
947 );
948 };
949}
950
951#[macro_export]
954#[cfg(feature = "std")]
955macro_rules! assert_eq_error_rate_float {
956 ($x:expr, $y:expr, $error:expr $(,)?) => {
957 assert!(
958 ($x >= $y - $error) && ($x <= $y + $error),
959 "{:?} != {:?} (with error rate {:?})",
960 $x,
961 $y,
962 $error,
963 );
964 };
965}
966
967#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
970pub struct OpaqueExtrinsic(Vec<u8>);
971
972impl OpaqueExtrinsic {
973 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, codec::Error> {
975 Self::decode(&mut bytes)
976 }
977}
978
979impl core::fmt::Debug for OpaqueExtrinsic {
980 #[cfg(feature = "std")]
981 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
982 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0))
983 }
984
985 #[cfg(not(feature = "std"))]
986 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
987 Ok(())
988 }
989}
990
991#[cfg(feature = "serde")]
992impl ::serde::Serialize for OpaqueExtrinsic {
993 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
994 where
995 S: ::serde::Serializer,
996 {
997 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
998 }
999}
1000
1001#[cfg(feature = "serde")]
1002impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1003 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1004 where
1005 D: ::serde::Deserializer<'a>,
1006 {
1007 let r = ::sp_core::bytes::deserialize(de)?;
1008 Decode::decode(&mut &r[..])
1009 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1010 }
1011}
1012
1013impl traits::ExtrinsicLike for OpaqueExtrinsic {
1014 fn is_bare(&self) -> bool {
1015 false
1016 }
1017}
1018
1019pub fn print(print: impl traits::Printable) {
1021 print.print();
1022}
1023
1024pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1039 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1040 let mut i = 0;
1041 let mut arr = [0; N];
1042 let s = s.as_bytes();
1043 while i < s.len() {
1044 arr[i] = s[i];
1045 i += 1;
1046 }
1047 arr
1048}
1049
1050pub enum TransactionOutcome<R> {
1052 Commit(R),
1054 Rollback(R),
1056}
1057
1058impl<R> TransactionOutcome<R> {
1059 pub fn into_inner(self) -> R {
1061 match self {
1062 Self::Commit(r) => r,
1063 Self::Rollback(r) => r,
1064 }
1065 }
1066}
1067
1068#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1070pub enum ExtrinsicInclusionMode {
1071 #[default]
1073 AllExtrinsics,
1074 OnlyInherents,
1076}
1077
1078#[derive(Decode, Encode, PartialEq, TypeInfo)]
1080pub struct OpaqueValue(Vec<u8>);
1081impl OpaqueValue {
1082 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1084 OpaqueValue(inner)
1085 }
1086
1087 pub fn decode<T: Decode>(&self) -> Option<T> {
1089 Decode::decode(&mut &self.0[..]).ok()
1090 }
1091}
1092
1093#[macro_export]
1096#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1097macro_rules! create_runtime_str {
1098 ( $y:expr ) => {{
1099 $crate::Cow::Borrowed($y)
1100 }};
1101}
1102#[doc(hidden)]
1104pub use alloc::borrow::Cow;
1105#[deprecated = "Use String or Cow<'static, str> instead"]
1108pub type RuntimeString = alloc::string::String;
1109
1110#[cfg(test)]
1111mod tests {
1112 use crate::traits::BlakeTwo256;
1113
1114 use super::*;
1115 use codec::{Decode, Encode};
1116 use sp_core::crypto::Pair;
1117 use sp_io::TestExternalities;
1118 use sp_state_machine::create_proof_check_backend;
1119
1120 #[test]
1121 fn opaque_extrinsic_serialization() {
1122 let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
1123 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1124 }
1125
1126 #[test]
1127 fn dispatch_error_encoding() {
1128 let error = DispatchError::Module(ModuleError {
1129 index: 1,
1130 error: [2, 0, 0, 0],
1131 message: Some("error message"),
1132 });
1133 let encoded = error.encode();
1134 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1135 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1136 assert_eq!(
1137 decoded,
1138 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1139 );
1140 }
1141
1142 #[test]
1143 fn dispatch_error_equality() {
1144 use DispatchError::*;
1145
1146 let variants = vec![
1147 Other("foo"),
1148 Other("bar"),
1149 CannotLookup,
1150 BadOrigin,
1151 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1152 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1153 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1154 ConsumerRemaining,
1155 NoProviders,
1156 Token(TokenError::FundsUnavailable),
1157 Token(TokenError::OnlyProvider),
1158 Token(TokenError::BelowMinimum),
1159 Token(TokenError::CannotCreate),
1160 Token(TokenError::UnknownAsset),
1161 Token(TokenError::Frozen),
1162 Arithmetic(ArithmeticError::Overflow),
1163 Arithmetic(ArithmeticError::Underflow),
1164 Arithmetic(ArithmeticError::DivisionByZero),
1165 ];
1166 for (i, variant) in variants.iter().enumerate() {
1167 for (j, other_variant) in variants.iter().enumerate() {
1168 if i == j {
1169 assert_eq!(variant, other_variant);
1170 } else {
1171 assert_ne!(variant, other_variant);
1172 }
1173 }
1174 }
1175
1176 assert_eq!(
1178 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1179 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1180 );
1181 }
1182
1183 #[test]
1184 fn multi_signature_ecdsa_verify_works() {
1185 let msg = &b"test-message"[..];
1186 let (pair, _) = ecdsa::Pair::generate();
1187
1188 let signature = pair.sign(&msg);
1189 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1190
1191 let multi_sig = MultiSignature::from(signature);
1192 let multi_signer = MultiSigner::from(pair.public());
1193 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1194
1195 let multi_signer = MultiSigner::from(pair.public());
1196 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1197 }
1198
1199 #[test]
1200 fn execute_and_generate_proof_works() {
1201 use codec::Encode;
1202 use sp_state_machine::Backend;
1203 let mut ext = TestExternalities::default();
1204
1205 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1206 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1207 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1208 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1209
1210 let pre_root = *ext.backend.root();
1211 let (_, proof) = ext.execute_and_prove(|| {
1212 sp_io::storage::get(b"a");
1213 sp_io::storage::get(b"b");
1214 sp_io::storage::get(b"v");
1215 sp_io::storage::get(b"d");
1216 });
1217
1218 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1219 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1220
1221 println!("proof size: {:?}", proof.encoded_size());
1223 println!("compact proof size: {:?}", compact_proof.encoded_size());
1224 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1225
1226 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1228 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1229
1230 let _ = ext.execute_and_prove(|| {
1231 sp_io::storage::set(b"a", &vec![1u8; 44]);
1232 });
1233
1234 ext.execute_with(|| {
1237 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1238 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1239 });
1240 }
1241}
1242
1243#[cfg(test)]
1246mod sp_core_tests {
1247 use super::*;
1248
1249 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1250 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1251
1252 #[test]
1253 #[should_panic]
1254 fn generate_feature_enabled_macro_panics() {
1255 if_test!(panic!("This should panic"));
1256 }
1257
1258 #[test]
1259 fn generate_feature_enabled_macro_works() {
1260 if_not_test!(panic!("This should not panic"));
1261 }
1262}