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(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;
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,
282 PartialEq,
283 Clone,
284 Encode,
285 Decode,
286 DecodeWithMemTracking,
287 MaxEncodedLen,
288 RuntimeDebug,
289 TypeInfo,
290)]
291pub enum MultiSignature {
292 Ed25519(ed25519::Signature),
294 Sr25519(sr25519::Signature),
296 Ecdsa(ecdsa::Signature),
298}
299
300impl From<ed25519::Signature> for MultiSignature {
301 fn from(x: ed25519::Signature) -> Self {
302 Self::Ed25519(x)
303 }
304}
305
306impl TryFrom<MultiSignature> for ed25519::Signature {
307 type Error = ();
308 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
309 if let MultiSignature::Ed25519(x) = m {
310 Ok(x)
311 } else {
312 Err(())
313 }
314 }
315}
316
317impl From<sr25519::Signature> for MultiSignature {
318 fn from(x: sr25519::Signature) -> Self {
319 Self::Sr25519(x)
320 }
321}
322
323impl TryFrom<MultiSignature> for sr25519::Signature {
324 type Error = ();
325 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
326 if let MultiSignature::Sr25519(x) = m {
327 Ok(x)
328 } else {
329 Err(())
330 }
331 }
332}
333
334impl From<ecdsa::Signature> for MultiSignature {
335 fn from(x: ecdsa::Signature) -> Self {
336 Self::Ecdsa(x)
337 }
338}
339
340impl TryFrom<MultiSignature> for ecdsa::Signature {
341 type Error = ();
342 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
343 if let MultiSignature::Ecdsa(x) = m {
344 Ok(x)
345 } else {
346 Err(())
347 }
348 }
349}
350
351#[derive(
353 Eq,
354 PartialEq,
355 Ord,
356 PartialOrd,
357 Clone,
358 Encode,
359 Decode,
360 DecodeWithMemTracking,
361 RuntimeDebug,
362 TypeInfo,
363)]
364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
365pub enum MultiSigner {
366 Ed25519(ed25519::Public),
368 Sr25519(sr25519::Public),
370 Ecdsa(ecdsa::Public),
372}
373
374impl FromEntropy for MultiSigner {
375 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
376 Ok(match input.read_byte()? % 3 {
377 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
378 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
379 2.. => Self::Ecdsa(FromEntropy::from_entropy(input)?),
380 })
381 }
382}
383
384impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
387 fn unchecked_from(x: T) -> Self {
388 ed25519::Public::unchecked_from(x.into()).into()
389 }
390}
391
392impl AsRef<[u8]> for MultiSigner {
393 fn as_ref(&self) -> &[u8] {
394 match *self {
395 Self::Ed25519(ref who) => who.as_ref(),
396 Self::Sr25519(ref who) => who.as_ref(),
397 Self::Ecdsa(ref who) => who.as_ref(),
398 }
399 }
400}
401
402impl traits::IdentifyAccount for MultiSigner {
403 type AccountId = AccountId32;
404 fn into_account(self) -> AccountId32 {
405 match self {
406 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
407 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
408 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
409 }
410 }
411}
412
413impl From<ed25519::Public> for MultiSigner {
414 fn from(x: ed25519::Public) -> Self {
415 Self::Ed25519(x)
416 }
417}
418
419impl TryFrom<MultiSigner> for ed25519::Public {
420 type Error = ();
421 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
422 if let MultiSigner::Ed25519(x) = m {
423 Ok(x)
424 } else {
425 Err(())
426 }
427 }
428}
429
430impl From<sr25519::Public> for MultiSigner {
431 fn from(x: sr25519::Public) -> Self {
432 Self::Sr25519(x)
433 }
434}
435
436impl TryFrom<MultiSigner> for sr25519::Public {
437 type Error = ();
438 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
439 if let MultiSigner::Sr25519(x) = m {
440 Ok(x)
441 } else {
442 Err(())
443 }
444 }
445}
446
447impl From<ecdsa::Public> for MultiSigner {
448 fn from(x: ecdsa::Public) -> Self {
449 Self::Ecdsa(x)
450 }
451}
452
453impl TryFrom<MultiSigner> for ecdsa::Public {
454 type Error = ();
455 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
456 if let MultiSigner::Ecdsa(x) = m {
457 Ok(x)
458 } else {
459 Err(())
460 }
461 }
462}
463
464#[cfg(feature = "std")]
465impl std::fmt::Display for MultiSigner {
466 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
467 match self {
468 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
469 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
470 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
471 }
472 }
473}
474
475impl Verify for MultiSignature {
476 type Signer = MultiSigner;
477 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
478 let who: [u8; 32] = *signer.as_ref();
479 match self {
480 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
481 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
482 Self::Ecdsa(sig) => {
483 let m = sp_io::hashing::blake2_256(msg.get());
484 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
485 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
486 },
487 }
488 }
489}
490
491#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
493#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
494pub struct AnySignature(H512);
495
496impl Verify for AnySignature {
497 type Signer = sr25519::Public;
498 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
499 let msg = msg.get();
500 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
501 .map(|s| s.verify(msg, signer))
502 .unwrap_or(false) ||
503 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
504 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
505 Err(()) => false,
506 Ok(signer) => s.verify(msg, &signer),
507 })
508 .unwrap_or(false)
509 }
510}
511
512impl From<sr25519::Signature> for AnySignature {
513 fn from(s: sr25519::Signature) -> Self {
514 Self(s.into())
515 }
516}
517
518impl From<ed25519::Signature> for AnySignature {
519 fn from(s: ed25519::Signature) -> Self {
520 Self(s.into())
521 }
522}
523
524impl From<DispatchError> for DispatchOutcome {
525 fn from(err: DispatchError) -> Self {
526 Err(err)
527 }
528}
529
530pub type DispatchResult = core::result::Result<(), DispatchError>;
534
535pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
538
539#[derive(
541 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
542)]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544pub struct ModuleError {
545 pub index: u8,
547 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
549 #[codec(skip)]
551 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
552 pub message: Option<&'static str>,
553}
554
555impl PartialEq for ModuleError {
556 fn eq(&self, other: &Self) -> bool {
557 (self.index == other.index) && (self.error == other.error)
558 }
559}
560
561#[derive(
563 Eq,
564 PartialEq,
565 Clone,
566 Copy,
567 Encode,
568 Decode,
569 DecodeWithMemTracking,
570 Debug,
571 TypeInfo,
572 MaxEncodedLen,
573)]
574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
575pub enum TransactionalError {
576 LimitReached,
578 NoLayer,
580}
581
582impl From<TransactionalError> for &'static str {
583 fn from(e: TransactionalError) -> &'static str {
584 match e {
585 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
586 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
587 }
588 }
589}
590
591impl From<TransactionalError> for DispatchError {
592 fn from(e: TransactionalError) -> DispatchError {
593 Self::Transactional(e)
594 }
595}
596
597#[derive(
599 Eq,
600 Clone,
601 Copy,
602 Encode,
603 Decode,
604 DecodeWithMemTracking,
605 Debug,
606 TypeInfo,
607 PartialEq,
608 MaxEncodedLen,
609)]
610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
611pub enum DispatchError {
612 Other(
614 #[codec(skip)]
615 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
616 &'static str,
617 ),
618 CannotLookup,
620 BadOrigin,
622 Module(ModuleError),
624 ConsumerRemaining,
626 NoProviders,
628 TooManyConsumers,
630 Token(TokenError),
632 Arithmetic(ArithmeticError),
634 Transactional(TransactionalError),
637 Exhausted,
639 Corruption,
641 Unavailable,
643 RootNotAllowed,
645 Trie(TrieError),
647}
648
649#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
652pub struct DispatchErrorWithPostInfo<Info>
653where
654 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
655{
656 pub post_info: Info,
658 pub error: DispatchError,
660}
661
662impl DispatchError {
663 pub fn stripped(self) -> Self {
665 match self {
666 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
667 DispatchError::Module(ModuleError { index, error, message: None }),
668 m => m,
669 }
670 }
671}
672
673impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
674where
675 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
676 E: Into<DispatchError>,
677{
678 fn from(error: E) -> Self {
679 Self { post_info: Default::default(), error: error.into() }
680 }
681}
682
683impl From<crate::traits::LookupError> for DispatchError {
684 fn from(_: crate::traits::LookupError) -> Self {
685 Self::CannotLookup
686 }
687}
688
689impl From<crate::traits::BadOrigin> for DispatchError {
690 fn from(_: crate::traits::BadOrigin) -> Self {
691 Self::BadOrigin
692 }
693}
694
695#[derive(
697 Eq,
698 PartialEq,
699 Clone,
700 Copy,
701 Encode,
702 Decode,
703 DecodeWithMemTracking,
704 Debug,
705 TypeInfo,
706 MaxEncodedLen,
707)]
708#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
709pub enum TokenError {
710 FundsUnavailable,
712 OnlyProvider,
715 BelowMinimum,
717 CannotCreate,
719 UnknownAsset,
721 Frozen,
723 Unsupported,
725 CannotCreateHold,
727 NotExpendable,
729 Blocked,
731}
732
733impl From<TokenError> for &'static str {
734 fn from(e: TokenError) -> &'static str {
735 match e {
736 TokenError::FundsUnavailable => "Funds are unavailable",
737 TokenError::OnlyProvider => "Account that must exist would die",
738 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
739 TokenError::CannotCreate => "Account cannot be created",
740 TokenError::UnknownAsset => "The asset in question is unknown",
741 TokenError::Frozen => "Funds exist but are frozen",
742 TokenError::Unsupported => "Operation is not supported by the asset",
743 TokenError::CannotCreateHold =>
744 "Account cannot be created for recording amount on hold",
745 TokenError::NotExpendable => "Account that is desired to remain would die",
746 TokenError::Blocked => "Account cannot receive the assets",
747 }
748 }
749}
750
751impl From<TokenError> for DispatchError {
752 fn from(e: TokenError) -> DispatchError {
753 Self::Token(e)
754 }
755}
756
757impl From<ArithmeticError> for DispatchError {
758 fn from(e: ArithmeticError) -> DispatchError {
759 Self::Arithmetic(e)
760 }
761}
762
763impl From<TrieError> for DispatchError {
764 fn from(e: TrieError) -> DispatchError {
765 Self::Trie(e)
766 }
767}
768
769impl From<&'static str> for DispatchError {
770 fn from(err: &'static str) -> DispatchError {
771 Self::Other(err)
772 }
773}
774
775impl From<DispatchError> for &'static str {
776 fn from(err: DispatchError) -> &'static str {
777 use DispatchError::*;
778 match err {
779 Other(msg) => msg,
780 CannotLookup => "Cannot lookup",
781 BadOrigin => "Bad origin",
782 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
783 ConsumerRemaining => "Consumer remaining",
784 NoProviders => "No providers",
785 TooManyConsumers => "Too many consumers",
786 Token(e) => e.into(),
787 Arithmetic(e) => e.into(),
788 Transactional(e) => e.into(),
789 Exhausted => "Resources exhausted",
790 Corruption => "State corrupt",
791 Unavailable => "Resource unavailable",
792 RootNotAllowed => "Root not allowed",
793 Trie(e) => e.into(),
794 }
795 }
796}
797
798impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
799where
800 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
801{
802 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
803 err.error.into()
804 }
805}
806
807impl traits::Printable for DispatchError {
808 fn print(&self) {
809 use DispatchError::*;
810 "DispatchError".print();
811 match self {
812 Other(err) => err.print(),
813 CannotLookup => "Cannot lookup".print(),
814 BadOrigin => "Bad origin".print(),
815 Module(ModuleError { index, error, message }) => {
816 index.print();
817 error.print();
818 if let Some(msg) = message {
819 msg.print();
820 }
821 },
822 ConsumerRemaining => "Consumer remaining".print(),
823 NoProviders => "No providers".print(),
824 TooManyConsumers => "Too many consumers".print(),
825 Token(e) => {
826 "Token error: ".print();
827 <&'static str>::from(*e).print();
828 },
829 Arithmetic(e) => {
830 "Arithmetic error: ".print();
831 <&'static str>::from(*e).print();
832 },
833 Transactional(e) => {
834 "Transactional error: ".print();
835 <&'static str>::from(*e).print();
836 },
837 Exhausted => "Resources exhausted".print(),
838 Corruption => "State corrupt".print(),
839 Unavailable => "Resource unavailable".print(),
840 RootNotAllowed => "Root not allowed".print(),
841 Trie(e) => {
842 "Trie error: ".print();
843 <&'static str>::from(*e).print();
844 },
845 }
846 }
847}
848
849impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
850where
851 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
852{
853 fn print(&self) {
854 self.error.print();
855 "PostInfo: ".print();
856 self.post_info.print();
857 }
858}
859
860pub type DispatchOutcome = Result<(), DispatchError>;
870
871pub type ApplyExtrinsicResult =
890 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
891
892pub type ApplyExtrinsicResultWithInfo<T> =
894 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
895
896pub type TryRuntimeError = DispatchError;
898
899pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
902 sig: &V,
903 item: &T,
904 signer: &<V::Signer as IdentifyAccount>::AccountId,
905) -> bool {
906 struct LazyEncode<F> {
911 inner: F,
912 encoded: Option<Vec<u8>>,
913 }
914
915 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
916 fn get(&mut self) -> &[u8] {
917 self.encoded.get_or_insert_with(&self.inner).as_slice()
918 }
919 }
920
921 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
922}
923
924#[macro_export]
942#[cfg(feature = "std")]
943macro_rules! assert_eq_error_rate {
944 ($x:expr, $y:expr, $error:expr $(,)?) => {
945 assert!(
946 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
947 ($x <= $crate::Saturating::saturating_add($y, $error)),
948 "{:?} != {:?} (with error rate {:?})",
949 $x,
950 $y,
951 $error,
952 );
953 };
954}
955
956#[macro_export]
959#[cfg(feature = "std")]
960macro_rules! assert_eq_error_rate_float {
961 ($x:expr, $y:expr, $error:expr $(,)?) => {
962 assert!(
963 ($x >= $y - $error) && ($x <= $y + $error),
964 "{:?} != {:?} (with error rate {:?})",
965 $x,
966 $y,
967 $error,
968 );
969 };
970}
971
972#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
975pub struct OpaqueExtrinsic(Vec<u8>);
976
977impl OpaqueExtrinsic {
978 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, codec::Error> {
980 Self::decode(&mut bytes)
981 }
982}
983
984impl core::fmt::Debug for OpaqueExtrinsic {
985 #[cfg(feature = "std")]
986 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
987 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0))
988 }
989
990 #[cfg(not(feature = "std"))]
991 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
992 Ok(())
993 }
994}
995
996#[cfg(feature = "serde")]
997impl ::serde::Serialize for OpaqueExtrinsic {
998 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
999 where
1000 S: ::serde::Serializer,
1001 {
1002 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1003 }
1004}
1005
1006#[cfg(feature = "serde")]
1007impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1008 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1009 where
1010 D: ::serde::Deserializer<'a>,
1011 {
1012 let r = ::sp_core::bytes::deserialize(de)?;
1013 Decode::decode(&mut &r[..])
1014 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1015 }
1016}
1017
1018impl traits::ExtrinsicLike for OpaqueExtrinsic {
1019 fn is_bare(&self) -> bool {
1020 false
1021 }
1022}
1023
1024pub fn print(print: impl traits::Printable) {
1026 print.print();
1027}
1028
1029pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1044 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1045 let mut i = 0;
1046 let mut arr = [0; N];
1047 let s = s.as_bytes();
1048 while i < s.len() {
1049 arr[i] = s[i];
1050 i += 1;
1051 }
1052 arr
1053}
1054
1055pub enum TransactionOutcome<R> {
1057 Commit(R),
1059 Rollback(R),
1061}
1062
1063impl<R> TransactionOutcome<R> {
1064 pub fn into_inner(self) -> R {
1066 match self {
1067 Self::Commit(r) => r,
1068 Self::Rollback(r) => r,
1069 }
1070 }
1071}
1072
1073#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1075pub enum ExtrinsicInclusionMode {
1076 #[default]
1078 AllExtrinsics,
1079 OnlyInherents,
1081}
1082
1083#[derive(Decode, Encode, PartialEq, TypeInfo)]
1085pub struct OpaqueValue(Vec<u8>);
1086impl OpaqueValue {
1087 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1089 OpaqueValue(inner)
1090 }
1091
1092 pub fn decode<T: Decode>(&self) -> Option<T> {
1094 Decode::decode(&mut &self.0[..]).ok()
1095 }
1096}
1097
1098#[macro_export]
1101#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1102macro_rules! create_runtime_str {
1103 ( $y:expr ) => {{
1104 $crate::Cow::Borrowed($y)
1105 }};
1106}
1107#[doc(hidden)]
1109pub use alloc::borrow::Cow;
1110#[deprecated = "Use String or Cow<'static, str> instead"]
1113pub type RuntimeString = alloc::string::String;
1114
1115#[cfg(test)]
1116mod tests {
1117 use crate::traits::BlakeTwo256;
1118
1119 use super::*;
1120 use codec::{Decode, Encode};
1121 use sp_core::crypto::Pair;
1122 use sp_io::TestExternalities;
1123 use sp_state_machine::create_proof_check_backend;
1124
1125 #[test]
1126 fn opaque_extrinsic_serialization() {
1127 let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
1128 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1129 }
1130
1131 #[test]
1132 fn dispatch_error_encoding() {
1133 let error = DispatchError::Module(ModuleError {
1134 index: 1,
1135 error: [2, 0, 0, 0],
1136 message: Some("error message"),
1137 });
1138 let encoded = error.encode();
1139 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1140 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1141 assert_eq!(
1142 decoded,
1143 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1144 );
1145 }
1146
1147 #[test]
1148 fn dispatch_error_equality() {
1149 use DispatchError::*;
1150
1151 let variants = vec![
1152 Other("foo"),
1153 Other("bar"),
1154 CannotLookup,
1155 BadOrigin,
1156 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1157 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1158 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1159 ConsumerRemaining,
1160 NoProviders,
1161 Token(TokenError::FundsUnavailable),
1162 Token(TokenError::OnlyProvider),
1163 Token(TokenError::BelowMinimum),
1164 Token(TokenError::CannotCreate),
1165 Token(TokenError::UnknownAsset),
1166 Token(TokenError::Frozen),
1167 Arithmetic(ArithmeticError::Overflow),
1168 Arithmetic(ArithmeticError::Underflow),
1169 Arithmetic(ArithmeticError::DivisionByZero),
1170 ];
1171 for (i, variant) in variants.iter().enumerate() {
1172 for (j, other_variant) in variants.iter().enumerate() {
1173 if i == j {
1174 assert_eq!(variant, other_variant);
1175 } else {
1176 assert_ne!(variant, other_variant);
1177 }
1178 }
1179 }
1180
1181 assert_eq!(
1183 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1184 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1185 );
1186 }
1187
1188 #[test]
1189 fn multi_signature_ecdsa_verify_works() {
1190 let msg = &b"test-message"[..];
1191 let (pair, _) = ecdsa::Pair::generate();
1192
1193 let signature = pair.sign(&msg);
1194 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1195
1196 let multi_sig = MultiSignature::from(signature);
1197 let multi_signer = MultiSigner::from(pair.public());
1198 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1199
1200 let multi_signer = MultiSigner::from(pair.public());
1201 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1202 }
1203
1204 #[test]
1205 fn execute_and_generate_proof_works() {
1206 use codec::Encode;
1207 use sp_state_machine::Backend;
1208 let mut ext = TestExternalities::default();
1209
1210 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1211 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1212 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1213 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1214
1215 let pre_root = *ext.backend.root();
1216 let (_, proof) = ext.execute_and_prove(|| {
1217 sp_io::storage::get(b"a");
1218 sp_io::storage::get(b"b");
1219 sp_io::storage::get(b"v");
1220 sp_io::storage::get(b"d");
1221 });
1222
1223 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1224 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1225
1226 println!("proof size: {:?}", proof.encoded_size());
1228 println!("compact proof size: {:?}", compact_proof.encoded_size());
1229 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1230
1231 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1233 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1234
1235 let _ = ext.execute_and_prove(|| {
1236 sp_io::storage::set(b"a", &vec![1u8; 44]);
1237 });
1238
1239 ext.execute_with(|| {
1242 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1243 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1244 });
1245 }
1246}
1247
1248#[cfg(test)]
1251mod sp_core_tests {
1252 use super::*;
1253
1254 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1255 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1256
1257 #[test]
1258 #[should_panic]
1259 fn generate_feature_enabled_macro_panics() {
1260 if_test!(panic!("This should panic"));
1261 }
1262
1263 #[test]
1264 fn generate_feature_enabled_macro_works() {
1265 if_not_test!(panic!("This should not panic"));
1266 }
1267}