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, 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(Eq, PartialEq, Clone, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
276pub enum MultiSignature {
277 Ed25519(ed25519::Signature),
279 Sr25519(sr25519::Signature),
281 Ecdsa(ecdsa::Signature),
283}
284
285impl From<ed25519::Signature> for MultiSignature {
286 fn from(x: ed25519::Signature) -> Self {
287 Self::Ed25519(x)
288 }
289}
290
291impl TryFrom<MultiSignature> for ed25519::Signature {
292 type Error = ();
293 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
294 if let MultiSignature::Ed25519(x) = m {
295 Ok(x)
296 } else {
297 Err(())
298 }
299 }
300}
301
302impl From<sr25519::Signature> for MultiSignature {
303 fn from(x: sr25519::Signature) -> Self {
304 Self::Sr25519(x)
305 }
306}
307
308impl TryFrom<MultiSignature> for sr25519::Signature {
309 type Error = ();
310 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
311 if let MultiSignature::Sr25519(x) = m {
312 Ok(x)
313 } else {
314 Err(())
315 }
316 }
317}
318
319impl From<ecdsa::Signature> for MultiSignature {
320 fn from(x: ecdsa::Signature) -> Self {
321 Self::Ecdsa(x)
322 }
323}
324
325impl TryFrom<MultiSignature> for ecdsa::Signature {
326 type Error = ();
327 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
328 if let MultiSignature::Ecdsa(x) = m {
329 Ok(x)
330 } else {
331 Err(())
332 }
333 }
334}
335
336#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
338#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
339pub enum MultiSigner {
340 Ed25519(ed25519::Public),
342 Sr25519(sr25519::Public),
344 Ecdsa(ecdsa::Public),
346}
347
348impl FromEntropy for MultiSigner {
349 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
350 Ok(match input.read_byte()? % 3 {
351 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
352 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
353 2.. => Self::Ecdsa(FromEntropy::from_entropy(input)?),
354 })
355 }
356}
357
358impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
361 fn unchecked_from(x: T) -> Self {
362 ed25519::Public::unchecked_from(x.into()).into()
363 }
364}
365
366impl AsRef<[u8]> for MultiSigner {
367 fn as_ref(&self) -> &[u8] {
368 match *self {
369 Self::Ed25519(ref who) => who.as_ref(),
370 Self::Sr25519(ref who) => who.as_ref(),
371 Self::Ecdsa(ref who) => who.as_ref(),
372 }
373 }
374}
375
376impl traits::IdentifyAccount for MultiSigner {
377 type AccountId = AccountId32;
378 fn into_account(self) -> AccountId32 {
379 match self {
380 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
381 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
382 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
383 }
384 }
385}
386
387impl From<ed25519::Public> for MultiSigner {
388 fn from(x: ed25519::Public) -> Self {
389 Self::Ed25519(x)
390 }
391}
392
393impl TryFrom<MultiSigner> for ed25519::Public {
394 type Error = ();
395 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
396 if let MultiSigner::Ed25519(x) = m {
397 Ok(x)
398 } else {
399 Err(())
400 }
401 }
402}
403
404impl From<sr25519::Public> for MultiSigner {
405 fn from(x: sr25519::Public) -> Self {
406 Self::Sr25519(x)
407 }
408}
409
410impl TryFrom<MultiSigner> for sr25519::Public {
411 type Error = ();
412 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
413 if let MultiSigner::Sr25519(x) = m {
414 Ok(x)
415 } else {
416 Err(())
417 }
418 }
419}
420
421impl From<ecdsa::Public> for MultiSigner {
422 fn from(x: ecdsa::Public) -> Self {
423 Self::Ecdsa(x)
424 }
425}
426
427impl TryFrom<MultiSigner> for ecdsa::Public {
428 type Error = ();
429 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
430 if let MultiSigner::Ecdsa(x) = m {
431 Ok(x)
432 } else {
433 Err(())
434 }
435 }
436}
437
438#[cfg(feature = "std")]
439impl std::fmt::Display for MultiSigner {
440 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
441 match self {
442 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
443 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
444 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
445 }
446 }
447}
448
449impl Verify for MultiSignature {
450 type Signer = MultiSigner;
451 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
452 let who: [u8; 32] = *signer.as_ref();
453 match self {
454 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
455 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
456 Self::Ecdsa(sig) => {
457 let m = sp_io::hashing::blake2_256(msg.get());
458 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
459 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
460 },
461 }
462 }
463}
464
465#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
468pub struct AnySignature(H512);
469
470impl Verify for AnySignature {
471 type Signer = sr25519::Public;
472 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
473 let msg = msg.get();
474 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
475 .map(|s| s.verify(msg, signer))
476 .unwrap_or(false) ||
477 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
478 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
479 Err(()) => false,
480 Ok(signer) => s.verify(msg, &signer),
481 })
482 .unwrap_or(false)
483 }
484}
485
486impl From<sr25519::Signature> for AnySignature {
487 fn from(s: sr25519::Signature) -> Self {
488 Self(s.into())
489 }
490}
491
492impl From<ed25519::Signature> for AnySignature {
493 fn from(s: ed25519::Signature) -> Self {
494 Self(s.into())
495 }
496}
497
498impl From<DispatchError> for DispatchOutcome {
499 fn from(err: DispatchError) -> Self {
500 Err(err)
501 }
502}
503
504pub type DispatchResult = core::result::Result<(), DispatchError>;
508
509pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
512
513#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
516pub struct ModuleError {
517 pub index: u8,
519 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
521 #[codec(skip)]
523 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
524 pub message: Option<&'static str>,
525}
526
527impl PartialEq for ModuleError {
528 fn eq(&self, other: &Self) -> bool {
529 (self.index == other.index) && (self.error == other.error)
530 }
531}
532
533#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
536pub enum TransactionalError {
537 LimitReached,
539 NoLayer,
541}
542
543impl From<TransactionalError> for &'static str {
544 fn from(e: TransactionalError) -> &'static str {
545 match e {
546 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
547 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
548 }
549 }
550}
551
552impl From<TransactionalError> for DispatchError {
553 fn from(e: TransactionalError) -> DispatchError {
554 Self::Transactional(e)
555 }
556}
557
558#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq, MaxEncodedLen)]
560#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
561pub enum DispatchError {
562 Other(
564 #[codec(skip)]
565 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
566 &'static str,
567 ),
568 CannotLookup,
570 BadOrigin,
572 Module(ModuleError),
574 ConsumerRemaining,
576 NoProviders,
578 TooManyConsumers,
580 Token(TokenError),
582 Arithmetic(ArithmeticError),
584 Transactional(TransactionalError),
587 Exhausted,
589 Corruption,
591 Unavailable,
593 RootNotAllowed,
595 Trie(TrieError),
597}
598
599#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
602pub struct DispatchErrorWithPostInfo<Info>
603where
604 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
605{
606 pub post_info: Info,
608 pub error: DispatchError,
610}
611
612impl DispatchError {
613 pub fn stripped(self) -> Self {
615 match self {
616 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
617 DispatchError::Module(ModuleError { index, error, message: None }),
618 m => m,
619 }
620 }
621}
622
623impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
624where
625 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
626 E: Into<DispatchError>,
627{
628 fn from(error: E) -> Self {
629 Self { post_info: Default::default(), error: error.into() }
630 }
631}
632
633impl From<crate::traits::LookupError> for DispatchError {
634 fn from(_: crate::traits::LookupError) -> Self {
635 Self::CannotLookup
636 }
637}
638
639impl From<crate::traits::BadOrigin> for DispatchError {
640 fn from(_: crate::traits::BadOrigin) -> Self {
641 Self::BadOrigin
642 }
643}
644
645#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
648pub enum TokenError {
649 FundsUnavailable,
651 OnlyProvider,
654 BelowMinimum,
656 CannotCreate,
658 UnknownAsset,
660 Frozen,
662 Unsupported,
664 CannotCreateHold,
666 NotExpendable,
668 Blocked,
670}
671
672impl From<TokenError> for &'static str {
673 fn from(e: TokenError) -> &'static str {
674 match e {
675 TokenError::FundsUnavailable => "Funds are unavailable",
676 TokenError::OnlyProvider => "Account that must exist would die",
677 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
678 TokenError::CannotCreate => "Account cannot be created",
679 TokenError::UnknownAsset => "The asset in question is unknown",
680 TokenError::Frozen => "Funds exist but are frozen",
681 TokenError::Unsupported => "Operation is not supported by the asset",
682 TokenError::CannotCreateHold =>
683 "Account cannot be created for recording amount on hold",
684 TokenError::NotExpendable => "Account that is desired to remain would die",
685 TokenError::Blocked => "Account cannot receive the assets",
686 }
687 }
688}
689
690impl From<TokenError> for DispatchError {
691 fn from(e: TokenError) -> DispatchError {
692 Self::Token(e)
693 }
694}
695
696impl From<ArithmeticError> for DispatchError {
697 fn from(e: ArithmeticError) -> DispatchError {
698 Self::Arithmetic(e)
699 }
700}
701
702impl From<TrieError> for DispatchError {
703 fn from(e: TrieError) -> DispatchError {
704 Self::Trie(e)
705 }
706}
707
708impl From<&'static str> for DispatchError {
709 fn from(err: &'static str) -> DispatchError {
710 Self::Other(err)
711 }
712}
713
714impl From<DispatchError> for &'static str {
715 fn from(err: DispatchError) -> &'static str {
716 use DispatchError::*;
717 match err {
718 Other(msg) => msg,
719 CannotLookup => "Cannot lookup",
720 BadOrigin => "Bad origin",
721 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
722 ConsumerRemaining => "Consumer remaining",
723 NoProviders => "No providers",
724 TooManyConsumers => "Too many consumers",
725 Token(e) => e.into(),
726 Arithmetic(e) => e.into(),
727 Transactional(e) => e.into(),
728 Exhausted => "Resources exhausted",
729 Corruption => "State corrupt",
730 Unavailable => "Resource unavailable",
731 RootNotAllowed => "Root not allowed",
732 Trie(e) => e.into(),
733 }
734 }
735}
736
737impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
738where
739 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
740{
741 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
742 err.error.into()
743 }
744}
745
746impl traits::Printable for DispatchError {
747 fn print(&self) {
748 use DispatchError::*;
749 "DispatchError".print();
750 match self {
751 Other(err) => err.print(),
752 CannotLookup => "Cannot lookup".print(),
753 BadOrigin => "Bad origin".print(),
754 Module(ModuleError { index, error, message }) => {
755 index.print();
756 error.print();
757 if let Some(msg) = message {
758 msg.print();
759 }
760 },
761 ConsumerRemaining => "Consumer remaining".print(),
762 NoProviders => "No providers".print(),
763 TooManyConsumers => "Too many consumers".print(),
764 Token(e) => {
765 "Token error: ".print();
766 <&'static str>::from(*e).print();
767 },
768 Arithmetic(e) => {
769 "Arithmetic error: ".print();
770 <&'static str>::from(*e).print();
771 },
772 Transactional(e) => {
773 "Transactional error: ".print();
774 <&'static str>::from(*e).print();
775 },
776 Exhausted => "Resources exhausted".print(),
777 Corruption => "State corrupt".print(),
778 Unavailable => "Resource unavailable".print(),
779 RootNotAllowed => "Root not allowed".print(),
780 Trie(e) => {
781 "Trie error: ".print();
782 <&'static str>::from(*e).print();
783 },
784 }
785 }
786}
787
788impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
789where
790 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
791{
792 fn print(&self) {
793 self.error.print();
794 "PostInfo: ".print();
795 self.post_info.print();
796 }
797}
798
799pub type DispatchOutcome = Result<(), DispatchError>;
809
810pub type ApplyExtrinsicResult =
829 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
830
831pub type ApplyExtrinsicResultWithInfo<T> =
833 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
834
835pub type TryRuntimeError = DispatchError;
837
838pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
841 sig: &V,
842 item: &T,
843 signer: &<V::Signer as IdentifyAccount>::AccountId,
844) -> bool {
845 struct LazyEncode<F> {
850 inner: F,
851 encoded: Option<Vec<u8>>,
852 }
853
854 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
855 fn get(&mut self) -> &[u8] {
856 self.encoded.get_or_insert_with(&self.inner).as_slice()
857 }
858 }
859
860 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
861}
862
863#[macro_export]
881#[cfg(feature = "std")]
882macro_rules! assert_eq_error_rate {
883 ($x:expr, $y:expr, $error:expr $(,)?) => {
884 assert!(
885 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
886 ($x <= $crate::Saturating::saturating_add($y, $error)),
887 "{:?} != {:?} (with error rate {:?})",
888 $x,
889 $y,
890 $error,
891 );
892 };
893}
894
895#[macro_export]
898#[cfg(feature = "std")]
899macro_rules! assert_eq_error_rate_float {
900 ($x:expr, $y:expr, $error:expr $(,)?) => {
901 assert!(
902 ($x >= $y - $error) && ($x <= $y + $error),
903 "{:?} != {:?} (with error rate {:?})",
904 $x,
905 $y,
906 $error,
907 );
908 };
909}
910
911#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, TypeInfo)]
914pub struct OpaqueExtrinsic(Vec<u8>);
915
916impl OpaqueExtrinsic {
917 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, codec::Error> {
919 Self::decode(&mut bytes)
920 }
921}
922
923impl core::fmt::Debug for OpaqueExtrinsic {
924 #[cfg(feature = "std")]
925 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
926 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0))
927 }
928
929 #[cfg(not(feature = "std"))]
930 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
931 Ok(())
932 }
933}
934
935#[cfg(feature = "serde")]
936impl ::serde::Serialize for OpaqueExtrinsic {
937 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
938 where
939 S: ::serde::Serializer,
940 {
941 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
942 }
943}
944
945#[cfg(feature = "serde")]
946impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
947 fn deserialize<D>(de: D) -> Result<Self, D::Error>
948 where
949 D: ::serde::Deserializer<'a>,
950 {
951 let r = ::sp_core::bytes::deserialize(de)?;
952 Decode::decode(&mut &r[..])
953 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
954 }
955}
956
957impl traits::ExtrinsicLike for OpaqueExtrinsic {
958 fn is_bare(&self) -> bool {
959 false
960 }
961}
962
963pub fn print(print: impl traits::Printable) {
965 print.print();
966}
967
968pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
983 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
984 let mut i = 0;
985 let mut arr = [0; N];
986 let s = s.as_bytes();
987 while i < s.len() {
988 arr[i] = s[i];
989 i += 1;
990 }
991 arr
992}
993
994pub enum TransactionOutcome<R> {
996 Commit(R),
998 Rollback(R),
1000}
1001
1002impl<R> TransactionOutcome<R> {
1003 pub fn into_inner(self) -> R {
1005 match self {
1006 Self::Commit(r) => r,
1007 Self::Rollback(r) => r,
1008 }
1009 }
1010}
1011
1012#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1014pub enum ExtrinsicInclusionMode {
1015 #[default]
1017 AllExtrinsics,
1018 OnlyInherents,
1020}
1021
1022#[derive(Decode, Encode, PartialEq, TypeInfo)]
1024pub struct OpaqueValue(Vec<u8>);
1025impl OpaqueValue {
1026 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1028 OpaqueValue(inner)
1029 }
1030
1031 pub fn decode<T: Decode>(&self) -> Option<T> {
1033 Decode::decode(&mut &self.0[..]).ok()
1034 }
1035}
1036
1037#[macro_export]
1040#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1041macro_rules! create_runtime_str {
1042 ( $y:expr ) => {{
1043 $crate::Cow::Borrowed($y)
1044 }};
1045}
1046#[doc(hidden)]
1048pub use alloc::borrow::Cow;
1049#[deprecated = "Use String or Cow<'static, str> instead"]
1052pub type RuntimeString = alloc::string::String;
1053
1054#[cfg(test)]
1055mod tests {
1056 use crate::traits::BlakeTwo256;
1057
1058 use super::*;
1059 use codec::{Decode, Encode};
1060 use sp_core::crypto::Pair;
1061 use sp_io::TestExternalities;
1062 use sp_state_machine::create_proof_check_backend;
1063
1064 #[test]
1065 fn opaque_extrinsic_serialization() {
1066 let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
1067 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1068 }
1069
1070 #[test]
1071 fn dispatch_error_encoding() {
1072 let error = DispatchError::Module(ModuleError {
1073 index: 1,
1074 error: [2, 0, 0, 0],
1075 message: Some("error message"),
1076 });
1077 let encoded = error.encode();
1078 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1079 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1080 assert_eq!(
1081 decoded,
1082 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1083 );
1084 }
1085
1086 #[test]
1087 fn dispatch_error_equality() {
1088 use DispatchError::*;
1089
1090 let variants = vec![
1091 Other("foo"),
1092 Other("bar"),
1093 CannotLookup,
1094 BadOrigin,
1095 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1096 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1097 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1098 ConsumerRemaining,
1099 NoProviders,
1100 Token(TokenError::FundsUnavailable),
1101 Token(TokenError::OnlyProvider),
1102 Token(TokenError::BelowMinimum),
1103 Token(TokenError::CannotCreate),
1104 Token(TokenError::UnknownAsset),
1105 Token(TokenError::Frozen),
1106 Arithmetic(ArithmeticError::Overflow),
1107 Arithmetic(ArithmeticError::Underflow),
1108 Arithmetic(ArithmeticError::DivisionByZero),
1109 ];
1110 for (i, variant) in variants.iter().enumerate() {
1111 for (j, other_variant) in variants.iter().enumerate() {
1112 if i == j {
1113 assert_eq!(variant, other_variant);
1114 } else {
1115 assert_ne!(variant, other_variant);
1116 }
1117 }
1118 }
1119
1120 assert_eq!(
1122 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1123 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1124 );
1125 }
1126
1127 #[test]
1128 fn multi_signature_ecdsa_verify_works() {
1129 let msg = &b"test-message"[..];
1130 let (pair, _) = ecdsa::Pair::generate();
1131
1132 let signature = pair.sign(&msg);
1133 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1134
1135 let multi_sig = MultiSignature::from(signature);
1136 let multi_signer = MultiSigner::from(pair.public());
1137 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1138
1139 let multi_signer = MultiSigner::from(pair.public());
1140 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1141 }
1142
1143 #[test]
1144 fn execute_and_generate_proof_works() {
1145 use codec::Encode;
1146 use sp_state_machine::Backend;
1147 let mut ext = TestExternalities::default();
1148
1149 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1150 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1151 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1152 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1153
1154 let pre_root = *ext.backend.root();
1155 let (_, proof) = ext.execute_and_prove(|| {
1156 sp_io::storage::get(b"a");
1157 sp_io::storage::get(b"b");
1158 sp_io::storage::get(b"v");
1159 sp_io::storage::get(b"d");
1160 });
1161
1162 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1163 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1164
1165 println!("proof size: {:?}", proof.encoded_size());
1167 println!("compact proof size: {:?}", compact_proof.encoded_size());
1168 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1169
1170 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1172 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1173
1174 let _ = ext.execute_and_prove(|| {
1175 sp_io::storage::set(b"a", &vec![1u8; 44]);
1176 });
1177
1178 ext.execute_with(|| {
1181 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1182 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1183 });
1184 }
1185}
1186
1187#[cfg(test)]
1190mod sp_core_tests {
1191 use super::*;
1192
1193 #[test]
1194 #[should_panic]
1195 fn generate_feature_enabled_macro_panics() {
1196 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1197 if_test!(panic!("This should panic"));
1198 }
1199
1200 #[test]
1201 fn generate_feature_enabled_macro_works() {
1202 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1203 if_not_test!(panic!("This should not panic"));
1204 }
1205}