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(
647 Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo,
648)]
649pub struct DispatchErrorWithPostInfo<Info>
650where
651 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
652{
653 pub post_info: Info,
655 pub error: DispatchError,
657}
658
659impl DispatchError {
660 pub fn stripped(self) -> Self {
662 match self {
663 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
664 DispatchError::Module(ModuleError { index, error, message: None }),
665 m => m,
666 }
667 }
668}
669
670impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
671where
672 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
673 E: Into<DispatchError>,
674{
675 fn from(error: E) -> Self {
676 Self { post_info: Default::default(), error: error.into() }
677 }
678}
679
680impl From<crate::traits::LookupError> for DispatchError {
681 fn from(_: crate::traits::LookupError) -> Self {
682 Self::CannotLookup
683 }
684}
685
686impl From<crate::traits::BadOrigin> for DispatchError {
687 fn from(_: crate::traits::BadOrigin) -> Self {
688 Self::BadOrigin
689 }
690}
691
692#[derive(
694 Eq,
695 PartialEq,
696 Clone,
697 Copy,
698 Encode,
699 Decode,
700 DecodeWithMemTracking,
701 Debug,
702 TypeInfo,
703 MaxEncodedLen,
704)]
705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
706pub enum TokenError {
707 FundsUnavailable,
709 OnlyProvider,
712 BelowMinimum,
714 CannotCreate,
716 UnknownAsset,
718 Frozen,
720 Unsupported,
722 CannotCreateHold,
724 NotExpendable,
726 Blocked,
728}
729
730impl From<TokenError> for &'static str {
731 fn from(e: TokenError) -> &'static str {
732 match e {
733 TokenError::FundsUnavailable => "Funds are unavailable",
734 TokenError::OnlyProvider => "Account that must exist would die",
735 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
736 TokenError::CannotCreate => "Account cannot be created",
737 TokenError::UnknownAsset => "The asset in question is unknown",
738 TokenError::Frozen => "Funds exist but are frozen",
739 TokenError::Unsupported => "Operation is not supported by the asset",
740 TokenError::CannotCreateHold =>
741 "Account cannot be created for recording amount on hold",
742 TokenError::NotExpendable => "Account that is desired to remain would die",
743 TokenError::Blocked => "Account cannot receive the assets",
744 }
745 }
746}
747
748impl From<TokenError> for DispatchError {
749 fn from(e: TokenError) -> DispatchError {
750 Self::Token(e)
751 }
752}
753
754impl From<ArithmeticError> for DispatchError {
755 fn from(e: ArithmeticError) -> DispatchError {
756 Self::Arithmetic(e)
757 }
758}
759
760impl From<TrieError> for DispatchError {
761 fn from(e: TrieError) -> DispatchError {
762 Self::Trie(e)
763 }
764}
765
766impl From<&'static str> for DispatchError {
767 fn from(err: &'static str) -> DispatchError {
768 Self::Other(err)
769 }
770}
771
772impl From<DispatchError> for &'static str {
773 fn from(err: DispatchError) -> &'static str {
774 use DispatchError::*;
775 match err {
776 Other(msg) => msg,
777 CannotLookup => "Cannot lookup",
778 BadOrigin => "Bad origin",
779 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
780 ConsumerRemaining => "Consumer remaining",
781 NoProviders => "No providers",
782 TooManyConsumers => "Too many consumers",
783 Token(e) => e.into(),
784 Arithmetic(e) => e.into(),
785 Transactional(e) => e.into(),
786 Exhausted => "Resources exhausted",
787 Corruption => "State corrupt",
788 Unavailable => "Resource unavailable",
789 RootNotAllowed => "Root not allowed",
790 Trie(e) => e.into(),
791 }
792 }
793}
794
795impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
796where
797 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
798{
799 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
800 err.error.into()
801 }
802}
803
804impl traits::Printable for DispatchError {
805 fn print(&self) {
806 use DispatchError::*;
807 "DispatchError".print();
808 match self {
809 Other(err) => err.print(),
810 CannotLookup => "Cannot lookup".print(),
811 BadOrigin => "Bad origin".print(),
812 Module(ModuleError { index, error, message }) => {
813 index.print();
814 error.print();
815 if let Some(msg) = message {
816 msg.print();
817 }
818 },
819 ConsumerRemaining => "Consumer remaining".print(),
820 NoProviders => "No providers".print(),
821 TooManyConsumers => "Too many consumers".print(),
822 Token(e) => {
823 "Token error: ".print();
824 <&'static str>::from(*e).print();
825 },
826 Arithmetic(e) => {
827 "Arithmetic error: ".print();
828 <&'static str>::from(*e).print();
829 },
830 Transactional(e) => {
831 "Transactional error: ".print();
832 <&'static str>::from(*e).print();
833 },
834 Exhausted => "Resources exhausted".print(),
835 Corruption => "State corrupt".print(),
836 Unavailable => "Resource unavailable".print(),
837 RootNotAllowed => "Root not allowed".print(),
838 Trie(e) => {
839 "Trie error: ".print();
840 <&'static str>::from(*e).print();
841 },
842 }
843 }
844}
845
846impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
847where
848 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
849{
850 fn print(&self) {
851 self.error.print();
852 "PostInfo: ".print();
853 self.post_info.print();
854 }
855}
856
857pub type DispatchOutcome = Result<(), DispatchError>;
867
868pub type ApplyExtrinsicResult =
887 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
888
889pub type ApplyExtrinsicResultWithInfo<T> =
891 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
892
893pub type TryRuntimeError = DispatchError;
895
896pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
899 sig: &V,
900 item: &T,
901 signer: &<V::Signer as IdentifyAccount>::AccountId,
902) -> bool {
903 struct LazyEncode<F> {
908 inner: F,
909 encoded: Option<Vec<u8>>,
910 }
911
912 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
913 fn get(&mut self) -> &[u8] {
914 self.encoded.get_or_insert_with(&self.inner).as_slice()
915 }
916 }
917
918 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
919}
920
921#[macro_export]
939#[cfg(feature = "std")]
940macro_rules! assert_eq_error_rate {
941 ($x:expr, $y:expr, $error:expr $(,)?) => {
942 assert!(
943 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
944 ($x <= $crate::Saturating::saturating_add($y, $error)),
945 "{:?} != {:?} (with error rate {:?})",
946 $x,
947 $y,
948 $error,
949 );
950 };
951}
952
953#[macro_export]
956#[cfg(feature = "std")]
957macro_rules! assert_eq_error_rate_float {
958 ($x:expr, $y:expr, $error:expr $(,)?) => {
959 assert!(
960 ($x >= $y - $error) && ($x <= $y + $error),
961 "{:?} != {:?} (with error rate {:?})",
962 $x,
963 $y,
964 $error,
965 );
966 };
967}
968
969#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
972pub struct OpaqueExtrinsic(Vec<u8>);
973
974impl OpaqueExtrinsic {
975 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, codec::Error> {
977 Self::decode(&mut bytes)
978 }
979}
980
981impl core::fmt::Debug for OpaqueExtrinsic {
982 #[cfg(feature = "std")]
983 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
984 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0))
985 }
986
987 #[cfg(not(feature = "std"))]
988 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
989 Ok(())
990 }
991}
992
993#[cfg(feature = "serde")]
994impl ::serde::Serialize for OpaqueExtrinsic {
995 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
996 where
997 S: ::serde::Serializer,
998 {
999 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1000 }
1001}
1002
1003#[cfg(feature = "serde")]
1004impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1005 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1006 where
1007 D: ::serde::Deserializer<'a>,
1008 {
1009 let r = ::sp_core::bytes::deserialize(de)?;
1010 Decode::decode(&mut &r[..])
1011 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1012 }
1013}
1014
1015impl traits::ExtrinsicLike for OpaqueExtrinsic {
1016 fn is_bare(&self) -> bool {
1017 false
1018 }
1019}
1020
1021pub fn print(print: impl traits::Printable) {
1023 print.print();
1024}
1025
1026pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1041 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1042 let mut i = 0;
1043 let mut arr = [0; N];
1044 let s = s.as_bytes();
1045 while i < s.len() {
1046 arr[i] = s[i];
1047 i += 1;
1048 }
1049 arr
1050}
1051
1052pub enum TransactionOutcome<R> {
1054 Commit(R),
1056 Rollback(R),
1058}
1059
1060impl<R> TransactionOutcome<R> {
1061 pub fn into_inner(self) -> R {
1063 match self {
1064 Self::Commit(r) => r,
1065 Self::Rollback(r) => r,
1066 }
1067 }
1068}
1069
1070#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1072pub enum ExtrinsicInclusionMode {
1073 #[default]
1075 AllExtrinsics,
1076 OnlyInherents,
1078}
1079
1080#[derive(Decode, Encode, PartialEq, TypeInfo)]
1082pub struct OpaqueValue(Vec<u8>);
1083impl OpaqueValue {
1084 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1086 OpaqueValue(inner)
1087 }
1088
1089 pub fn decode<T: Decode>(&self) -> Option<T> {
1091 Decode::decode(&mut &self.0[..]).ok()
1092 }
1093}
1094
1095#[macro_export]
1098#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1099macro_rules! create_runtime_str {
1100 ( $y:expr ) => {{
1101 $crate::Cow::Borrowed($y)
1102 }};
1103}
1104#[doc(hidden)]
1106pub use alloc::borrow::Cow;
1107#[deprecated = "Use String or Cow<'static, str> instead"]
1110pub type RuntimeString = alloc::string::String;
1111
1112#[cfg(test)]
1113mod tests {
1114 use crate::traits::BlakeTwo256;
1115
1116 use super::*;
1117 use codec::{Decode, Encode};
1118 use sp_core::crypto::Pair;
1119 use sp_io::TestExternalities;
1120 use sp_state_machine::create_proof_check_backend;
1121
1122 #[test]
1123 fn opaque_extrinsic_serialization() {
1124 let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
1125 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1126 }
1127
1128 #[test]
1129 fn dispatch_error_encoding() {
1130 let error = DispatchError::Module(ModuleError {
1131 index: 1,
1132 error: [2, 0, 0, 0],
1133 message: Some("error message"),
1134 });
1135 let encoded = error.encode();
1136 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1137 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1138 assert_eq!(
1139 decoded,
1140 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1141 );
1142 }
1143
1144 #[test]
1145 fn dispatch_error_equality() {
1146 use DispatchError::*;
1147
1148 let variants = vec![
1149 Other("foo"),
1150 Other("bar"),
1151 CannotLookup,
1152 BadOrigin,
1153 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1154 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1155 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1156 ConsumerRemaining,
1157 NoProviders,
1158 Token(TokenError::FundsUnavailable),
1159 Token(TokenError::OnlyProvider),
1160 Token(TokenError::BelowMinimum),
1161 Token(TokenError::CannotCreate),
1162 Token(TokenError::UnknownAsset),
1163 Token(TokenError::Frozen),
1164 Arithmetic(ArithmeticError::Overflow),
1165 Arithmetic(ArithmeticError::Underflow),
1166 Arithmetic(ArithmeticError::DivisionByZero),
1167 ];
1168 for (i, variant) in variants.iter().enumerate() {
1169 for (j, other_variant) in variants.iter().enumerate() {
1170 if i == j {
1171 assert_eq!(variant, other_variant);
1172 } else {
1173 assert_ne!(variant, other_variant);
1174 }
1175 }
1176 }
1177
1178 assert_eq!(
1180 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1181 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1182 );
1183 }
1184
1185 #[test]
1186 fn multi_signature_ecdsa_verify_works() {
1187 let msg = &b"test-message"[..];
1188 let (pair, _) = ecdsa::Pair::generate();
1189
1190 let signature = pair.sign(&msg);
1191 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1192
1193 let multi_sig = MultiSignature::from(signature);
1194 let multi_signer = MultiSigner::from(pair.public());
1195 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1196
1197 let multi_signer = MultiSigner::from(pair.public());
1198 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1199 }
1200
1201 #[test]
1202 fn execute_and_generate_proof_works() {
1203 use codec::Encode;
1204 use sp_state_machine::Backend;
1205 let mut ext = TestExternalities::default();
1206
1207 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1208 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1209 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1210 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1211
1212 let pre_root = *ext.backend.root();
1213 let (_, proof) = ext.execute_and_prove(|| {
1214 sp_io::storage::get(b"a");
1215 sp_io::storage::get(b"b");
1216 sp_io::storage::get(b"v");
1217 sp_io::storage::get(b"d");
1218 });
1219
1220 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1221 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1222
1223 println!("proof size: {:?}", proof.encoded_size());
1225 println!("compact proof size: {:?}", compact_proof.encoded_size());
1226 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1227
1228 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1230 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1231
1232 let _ = ext.execute_and_prove(|| {
1233 sp_io::storage::set(b"a", &vec![1u8; 44]);
1234 });
1235
1236 ext.execute_with(|| {
1239 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1240 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1241 });
1242 }
1243}
1244
1245#[cfg(test)]
1248mod sp_core_tests {
1249 use super::*;
1250
1251 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1252 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1253
1254 #[test]
1255 #[should_panic]
1256 fn generate_feature_enabled_macro_panics() {
1257 if_test!(panic!("This should panic"));
1258 }
1259
1260 #[test]
1261 fn generate_feature_enabled_macro_works() {
1262 if_not_test!(panic!("This should not panic"));
1263 }
1264}