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::{format, 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;
93mod runtime_string;
94#[cfg(feature = "std")]
95pub mod testing;
96pub mod traits;
97pub mod transaction_validity;
98pub mod type_with_default;
99
100pub use crate::runtime_string::*;
101
102pub use multiaddress::MultiAddress;
104
105use proving_trie::TrieError;
106
107pub use generic::{Digest, DigestItem};
109
110pub use sp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
111pub use sp_core::{
113 bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec},
114 crypto::{key_types, AccountId32, CryptoType, CryptoTypeId, KeyTypeId},
115 TypeId,
116};
117#[cfg(feature = "std")]
119pub use sp_core::{bounded_btree_map, bounded_vec};
120
121pub use sp_core::RuntimeDebug;
123
124pub use sp_arithmetic::biguint;
126pub use sp_arithmetic::helpers_128bit;
128pub use sp_arithmetic::{
130 traits::SaturatedConversion, ArithmeticError, FixedI128, FixedI64, FixedPointNumber,
131 FixedPointOperand, FixedU128, FixedU64, InnerOf, PerThing, PerU16, Perbill, Percent, Permill,
132 Perquintill, Rational128, Rounding, UpperOf,
133};
134
135pub use either::Either;
136
137pub const MAX_MODULE_ERROR_ENCODED_SIZE: usize = 4;
140
141pub type Justification = (ConsensusEngineId, EncodedJustification);
153
154pub type EncodedJustification = Vec<u8>;
156
157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
160#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
161pub struct Justifications(Vec<Justification>);
162
163impl Justifications {
164 pub fn iter(&self) -> impl Iterator<Item = &Justification> {
166 self.0.iter()
167 }
168
169 pub fn append(&mut self, justification: Justification) -> bool {
173 if self.get(justification.0).is_some() {
174 return false
175 }
176 self.0.push(justification);
177 true
178 }
179
180 pub fn get(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> {
183 self.iter().find(|j| j.0 == engine_id).map(|j| &j.1)
184 }
185
186 pub fn remove(&mut self, engine_id: ConsensusEngineId) {
188 self.0.retain(|j| j.0 != engine_id)
189 }
190
191 pub fn into_justification(self, engine_id: ConsensusEngineId) -> Option<EncodedJustification> {
194 self.into_iter().find(|j| j.0 == engine_id).map(|j| j.1)
195 }
196}
197
198impl IntoIterator for Justifications {
199 type Item = Justification;
200 type IntoIter = alloc::vec::IntoIter<Self::Item>;
201
202 fn into_iter(self) -> Self::IntoIter {
203 self.0.into_iter()
204 }
205}
206
207impl From<Justification> for Justifications {
208 fn from(justification: Justification) -> Self {
209 Self(vec![justification])
210 }
211}
212
213use traits::{Lazy, Verify};
214
215use crate::traits::IdentifyAccount;
216#[cfg(feature = "serde")]
217pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
218
219#[cfg(feature = "std")]
221pub trait BuildStorage {
222 fn build_storage(&self) -> Result<sp_core::storage::Storage, String> {
224 let mut storage = Default::default();
225 self.assimilate_storage(&mut storage)?;
226 Ok(storage)
227 }
228 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String>;
230}
231
232#[cfg(feature = "std")]
234#[deprecated(
235 note = "`BuildModuleGenesisStorage` is planned to be removed in December 2023. Use `BuildStorage` instead of it."
236)]
237pub trait BuildModuleGenesisStorage<T, I>: Sized {
238 fn build_module_genesis_storage(
240 &self,
241 storage: &mut sp_core::storage::Storage,
242 ) -> Result<(), String>;
243}
244
245#[cfg(feature = "std")]
246impl BuildStorage for sp_core::storage::Storage {
247 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String> {
248 storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone())));
249 for (k, other_map) in self.children_default.iter() {
250 let k = k.clone();
251 if let Some(map) = storage.children_default.get_mut(&k) {
252 map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone())));
253 if !map.child_info.try_update(&other_map.child_info) {
254 return Err("Incompatible child info update".to_string())
255 }
256 } else {
257 storage.children_default.insert(k, other_map.clone());
258 }
259 }
260 Ok(())
261 }
262}
263
264#[cfg(feature = "std")]
265impl BuildStorage for () {
266 fn assimilate_storage(&self, _: &mut sp_core::storage::Storage) -> Result<(), String> {
267 Err("`assimilate_storage` not implemented for `()`".into())
268 }
269}
270
271pub type ConsensusEngineId = [u8; 4];
273
274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
276#[derive(Eq, PartialEq, Clone, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
277pub enum MultiSignature {
278 Ed25519(ed25519::Signature),
280 Sr25519(sr25519::Signature),
282 Ecdsa(ecdsa::Signature),
284}
285
286impl From<ed25519::Signature> for MultiSignature {
287 fn from(x: ed25519::Signature) -> Self {
288 Self::Ed25519(x)
289 }
290}
291
292impl TryFrom<MultiSignature> for ed25519::Signature {
293 type Error = ();
294 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
295 if let MultiSignature::Ed25519(x) = m {
296 Ok(x)
297 } else {
298 Err(())
299 }
300 }
301}
302
303impl From<sr25519::Signature> for MultiSignature {
304 fn from(x: sr25519::Signature) -> Self {
305 Self::Sr25519(x)
306 }
307}
308
309impl TryFrom<MultiSignature> for sr25519::Signature {
310 type Error = ();
311 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
312 if let MultiSignature::Sr25519(x) = m {
313 Ok(x)
314 } else {
315 Err(())
316 }
317 }
318}
319
320impl From<ecdsa::Signature> for MultiSignature {
321 fn from(x: ecdsa::Signature) -> Self {
322 Self::Ecdsa(x)
323 }
324}
325
326impl TryFrom<MultiSignature> for ecdsa::Signature {
327 type Error = ();
328 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
329 if let MultiSignature::Ecdsa(x) = m {
330 Ok(x)
331 } else {
332 Err(())
333 }
334 }
335}
336
337#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
340pub enum MultiSigner {
341 Ed25519(ed25519::Public),
343 Sr25519(sr25519::Public),
345 Ecdsa(ecdsa::Public),
347}
348
349impl FromEntropy for MultiSigner {
350 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
351 Ok(match input.read_byte()? % 3 {
352 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
353 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
354 2.. => Self::Ecdsa(FromEntropy::from_entropy(input)?),
355 })
356 }
357}
358
359impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
362 fn unchecked_from(x: T) -> Self {
363 ed25519::Public::unchecked_from(x.into()).into()
364 }
365}
366
367impl AsRef<[u8]> for MultiSigner {
368 fn as_ref(&self) -> &[u8] {
369 match *self {
370 Self::Ed25519(ref who) => who.as_ref(),
371 Self::Sr25519(ref who) => who.as_ref(),
372 Self::Ecdsa(ref who) => who.as_ref(),
373 }
374 }
375}
376
377impl traits::IdentifyAccount for MultiSigner {
378 type AccountId = AccountId32;
379 fn into_account(self) -> AccountId32 {
380 match self {
381 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
382 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
383 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
384 }
385 }
386}
387
388impl From<ed25519::Public> for MultiSigner {
389 fn from(x: ed25519::Public) -> Self {
390 Self::Ed25519(x)
391 }
392}
393
394impl TryFrom<MultiSigner> for ed25519::Public {
395 type Error = ();
396 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
397 if let MultiSigner::Ed25519(x) = m {
398 Ok(x)
399 } else {
400 Err(())
401 }
402 }
403}
404
405impl From<sr25519::Public> for MultiSigner {
406 fn from(x: sr25519::Public) -> Self {
407 Self::Sr25519(x)
408 }
409}
410
411impl TryFrom<MultiSigner> for sr25519::Public {
412 type Error = ();
413 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
414 if let MultiSigner::Sr25519(x) = m {
415 Ok(x)
416 } else {
417 Err(())
418 }
419 }
420}
421
422impl From<ecdsa::Public> for MultiSigner {
423 fn from(x: ecdsa::Public) -> Self {
424 Self::Ecdsa(x)
425 }
426}
427
428impl TryFrom<MultiSigner> for ecdsa::Public {
429 type Error = ();
430 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
431 if let MultiSigner::Ecdsa(x) = m {
432 Ok(x)
433 } else {
434 Err(())
435 }
436 }
437}
438
439#[cfg(feature = "std")]
440impl std::fmt::Display for MultiSigner {
441 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
442 match self {
443 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
444 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
445 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
446 }
447 }
448}
449
450impl Verify for MultiSignature {
451 type Signer = MultiSigner;
452 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
453 let who: [u8; 32] = *signer.as_ref();
454 match self {
455 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
456 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
457 Self::Ecdsa(sig) => {
458 let m = sp_io::hashing::blake2_256(msg.get());
459 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
460 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
461 },
462 }
463 }
464}
465
466#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
468#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
469pub struct AnySignature(H512);
470
471impl Verify for AnySignature {
472 type Signer = sr25519::Public;
473 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
474 let msg = msg.get();
475 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
476 .map(|s| s.verify(msg, signer))
477 .unwrap_or(false) ||
478 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
479 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
480 Err(()) => false,
481 Ok(signer) => s.verify(msg, &signer),
482 })
483 .unwrap_or(false)
484 }
485}
486
487impl From<sr25519::Signature> for AnySignature {
488 fn from(s: sr25519::Signature) -> Self {
489 Self(s.into())
490 }
491}
492
493impl From<ed25519::Signature> for AnySignature {
494 fn from(s: ed25519::Signature) -> Self {
495 Self(s.into())
496 }
497}
498
499impl From<DispatchError> for DispatchOutcome {
500 fn from(err: DispatchError) -> Self {
501 Err(err)
502 }
503}
504
505pub type DispatchResult = core::result::Result<(), DispatchError>;
509
510pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
513
514#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
517pub struct ModuleError {
518 pub index: u8,
520 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
522 #[codec(skip)]
524 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
525 pub message: Option<&'static str>,
526}
527
528impl PartialEq for ModuleError {
529 fn eq(&self, other: &Self) -> bool {
530 (self.index == other.index) && (self.error == other.error)
531 }
532}
533
534#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
536#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
537pub enum TransactionalError {
538 LimitReached,
540 NoLayer,
542}
543
544impl From<TransactionalError> for &'static str {
545 fn from(e: TransactionalError) -> &'static str {
546 match e {
547 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
548 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
549 }
550 }
551}
552
553impl From<TransactionalError> for DispatchError {
554 fn from(e: TransactionalError) -> DispatchError {
555 Self::Transactional(e)
556 }
557}
558
559#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq, MaxEncodedLen)]
561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
562pub enum DispatchError {
563 Other(
565 #[codec(skip)]
566 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
567 &'static str,
568 ),
569 CannotLookup,
571 BadOrigin,
573 Module(ModuleError),
575 ConsumerRemaining,
577 NoProviders,
579 TooManyConsumers,
581 Token(TokenError),
583 Arithmetic(ArithmeticError),
585 Transactional(TransactionalError),
588 Exhausted,
590 Corruption,
592 Unavailable,
594 RootNotAllowed,
596 Trie(TrieError),
598}
599
600#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
603pub struct DispatchErrorWithPostInfo<Info>
604where
605 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
606{
607 pub post_info: Info,
609 pub error: DispatchError,
611}
612
613impl DispatchError {
614 pub fn stripped(self) -> Self {
616 match self {
617 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
618 DispatchError::Module(ModuleError { index, error, message: None }),
619 m => m,
620 }
621 }
622}
623
624impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
625where
626 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
627 E: Into<DispatchError>,
628{
629 fn from(error: E) -> Self {
630 Self { post_info: Default::default(), error: error.into() }
631 }
632}
633
634impl From<crate::traits::LookupError> for DispatchError {
635 fn from(_: crate::traits::LookupError) -> Self {
636 Self::CannotLookup
637 }
638}
639
640impl From<crate::traits::BadOrigin> for DispatchError {
641 fn from(_: crate::traits::BadOrigin) -> Self {
642 Self::BadOrigin
643 }
644}
645
646#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
649pub enum TokenError {
650 FundsUnavailable,
652 OnlyProvider,
655 BelowMinimum,
657 CannotCreate,
659 UnknownAsset,
661 Frozen,
663 Unsupported,
665 CannotCreateHold,
667 NotExpendable,
669 Blocked,
671}
672
673impl From<TokenError> for &'static str {
674 fn from(e: TokenError) -> &'static str {
675 match e {
676 TokenError::FundsUnavailable => "Funds are unavailable",
677 TokenError::OnlyProvider => "Account that must exist would die",
678 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
679 TokenError::CannotCreate => "Account cannot be created",
680 TokenError::UnknownAsset => "The asset in question is unknown",
681 TokenError::Frozen => "Funds exist but are frozen",
682 TokenError::Unsupported => "Operation is not supported by the asset",
683 TokenError::CannotCreateHold =>
684 "Account cannot be created for recording amount on hold",
685 TokenError::NotExpendable => "Account that is desired to remain would die",
686 TokenError::Blocked => "Account cannot receive the assets",
687 }
688 }
689}
690
691impl From<TokenError> for DispatchError {
692 fn from(e: TokenError) -> DispatchError {
693 Self::Token(e)
694 }
695}
696
697impl From<ArithmeticError> for DispatchError {
698 fn from(e: ArithmeticError) -> DispatchError {
699 Self::Arithmetic(e)
700 }
701}
702
703impl From<TrieError> for DispatchError {
704 fn from(e: TrieError) -> DispatchError {
705 Self::Trie(e)
706 }
707}
708
709impl From<&'static str> for DispatchError {
710 fn from(err: &'static str) -> DispatchError {
711 Self::Other(err)
712 }
713}
714
715impl From<DispatchError> for &'static str {
716 fn from(err: DispatchError) -> &'static str {
717 use DispatchError::*;
718 match err {
719 Other(msg) => msg,
720 CannotLookup => "Cannot lookup",
721 BadOrigin => "Bad origin",
722 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
723 ConsumerRemaining => "Consumer remaining",
724 NoProviders => "No providers",
725 TooManyConsumers => "Too many consumers",
726 Token(e) => e.into(),
727 Arithmetic(e) => e.into(),
728 Transactional(e) => e.into(),
729 Exhausted => "Resources exhausted",
730 Corruption => "State corrupt",
731 Unavailable => "Resource unavailable",
732 RootNotAllowed => "Root not allowed",
733 Trie(e) => e.into(),
734 }
735 }
736}
737
738impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
739where
740 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
741{
742 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
743 err.error.into()
744 }
745}
746
747impl traits::Printable for DispatchError {
748 fn print(&self) {
749 use DispatchError::*;
750 "DispatchError".print();
751 match self {
752 Other(err) => err.print(),
753 CannotLookup => "Cannot lookup".print(),
754 BadOrigin => "Bad origin".print(),
755 Module(ModuleError { index, error, message }) => {
756 index.print();
757 error.print();
758 if let Some(msg) = message {
759 msg.print();
760 }
761 },
762 ConsumerRemaining => "Consumer remaining".print(),
763 NoProviders => "No providers".print(),
764 TooManyConsumers => "Too many consumers".print(),
765 Token(e) => {
766 "Token error: ".print();
767 <&'static str>::from(*e).print();
768 },
769 Arithmetic(e) => {
770 "Arithmetic error: ".print();
771 <&'static str>::from(*e).print();
772 },
773 Transactional(e) => {
774 "Transactional error: ".print();
775 <&'static str>::from(*e).print();
776 },
777 Exhausted => "Resources exhausted".print(),
778 Corruption => "State corrupt".print(),
779 Unavailable => "Resource unavailable".print(),
780 RootNotAllowed => "Root not allowed".print(),
781 Trie(e) => {
782 "Trie error: ".print();
783 <&'static str>::from(*e).print();
784 },
785 }
786 }
787}
788
789impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
790where
791 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
792{
793 fn print(&self) {
794 self.error.print();
795 "PostInfo: ".print();
796 self.post_info.print();
797 }
798}
799
800pub type DispatchOutcome = Result<(), DispatchError>;
810
811pub type ApplyExtrinsicResult =
830 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
831
832pub type ApplyExtrinsicResultWithInfo<T> =
834 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
835
836pub type TryRuntimeError = DispatchError;
838
839pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
842 sig: &V,
843 item: &T,
844 signer: &<V::Signer as IdentifyAccount>::AccountId,
845) -> bool {
846 struct LazyEncode<F> {
851 inner: F,
852 encoded: Option<Vec<u8>>,
853 }
854
855 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
856 fn get(&mut self) -> &[u8] {
857 self.encoded.get_or_insert_with(&self.inner).as_slice()
858 }
859 }
860
861 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
862}
863
864#[macro_export]
882#[cfg(feature = "std")]
883macro_rules! assert_eq_error_rate {
884 ($x:expr, $y:expr, $error:expr $(,)?) => {
885 assert!(
886 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
887 ($x <= $crate::Saturating::saturating_add($y, $error)),
888 "{:?} != {:?} (with error rate {:?})",
889 $x,
890 $y,
891 $error,
892 );
893 };
894}
895
896#[macro_export]
899#[cfg(feature = "std")]
900macro_rules! assert_eq_error_rate_float {
901 ($x:expr, $y:expr, $error:expr $(,)?) => {
902 assert!(
903 ($x >= $y - $error) && ($x <= $y + $error),
904 "{:?} != {:?} (with error rate {:?})",
905 $x,
906 $y,
907 $error,
908 );
909 };
910}
911
912#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, TypeInfo)]
915pub struct OpaqueExtrinsic(Vec<u8>);
916
917impl OpaqueExtrinsic {
918 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, codec::Error> {
920 Self::decode(&mut bytes)
921 }
922}
923
924impl core::fmt::Debug for OpaqueExtrinsic {
925 #[cfg(feature = "std")]
926 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
927 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0))
928 }
929
930 #[cfg(not(feature = "std"))]
931 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
932 Ok(())
933 }
934}
935
936#[cfg(feature = "serde")]
937impl ::serde::Serialize for OpaqueExtrinsic {
938 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
939 where
940 S: ::serde::Serializer,
941 {
942 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
943 }
944}
945
946#[cfg(feature = "serde")]
947impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
948 fn deserialize<D>(de: D) -> Result<Self, D::Error>
949 where
950 D: ::serde::Deserializer<'a>,
951 {
952 let r = ::sp_core::bytes::deserialize(de)?;
953 Decode::decode(&mut &r[..])
954 .map_err(|e| ::serde::de::Error::custom(format!("Decode error: {}", e)))
955 }
956}
957
958impl traits::Extrinsic for OpaqueExtrinsic {
959 type Call = ();
960 type SignaturePayload = ();
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#[cfg(test)]
1038mod tests {
1039 use crate::traits::BlakeTwo256;
1040
1041 use super::*;
1042 use codec::{Decode, Encode};
1043 use sp_core::crypto::Pair;
1044 use sp_io::TestExternalities;
1045 use sp_state_machine::create_proof_check_backend;
1046
1047 #[test]
1048 fn opaque_extrinsic_serialization() {
1049 let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
1050 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1051 }
1052
1053 #[test]
1054 fn dispatch_error_encoding() {
1055 let error = DispatchError::Module(ModuleError {
1056 index: 1,
1057 error: [2, 0, 0, 0],
1058 message: Some("error message"),
1059 });
1060 let encoded = error.encode();
1061 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1062 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1063 assert_eq!(
1064 decoded,
1065 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1066 );
1067 }
1068
1069 #[test]
1070 fn dispatch_error_equality() {
1071 use DispatchError::*;
1072
1073 let variants = vec![
1074 Other("foo"),
1075 Other("bar"),
1076 CannotLookup,
1077 BadOrigin,
1078 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1079 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1080 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1081 ConsumerRemaining,
1082 NoProviders,
1083 Token(TokenError::FundsUnavailable),
1084 Token(TokenError::OnlyProvider),
1085 Token(TokenError::BelowMinimum),
1086 Token(TokenError::CannotCreate),
1087 Token(TokenError::UnknownAsset),
1088 Token(TokenError::Frozen),
1089 Arithmetic(ArithmeticError::Overflow),
1090 Arithmetic(ArithmeticError::Underflow),
1091 Arithmetic(ArithmeticError::DivisionByZero),
1092 ];
1093 for (i, variant) in variants.iter().enumerate() {
1094 for (j, other_variant) in variants.iter().enumerate() {
1095 if i == j {
1096 assert_eq!(variant, other_variant);
1097 } else {
1098 assert_ne!(variant, other_variant);
1099 }
1100 }
1101 }
1102
1103 assert_eq!(
1105 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1106 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1107 );
1108 }
1109
1110 #[test]
1111 fn multi_signature_ecdsa_verify_works() {
1112 let msg = &b"test-message"[..];
1113 let (pair, _) = ecdsa::Pair::generate();
1114
1115 let signature = pair.sign(&msg);
1116 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1117
1118 let multi_sig = MultiSignature::from(signature);
1119 let multi_signer = MultiSigner::from(pair.public());
1120 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1121
1122 let multi_signer = MultiSigner::from(pair.public());
1123 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1124 }
1125
1126 #[test]
1127 fn execute_and_generate_proof_works() {
1128 use codec::Encode;
1129 use sp_state_machine::Backend;
1130 let mut ext = TestExternalities::default();
1131
1132 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1133 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1134 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1135 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1136
1137 let pre_root = *ext.backend.root();
1138 let (_, proof) = ext.execute_and_prove(|| {
1139 sp_io::storage::get(b"a");
1140 sp_io::storage::get(b"b");
1141 sp_io::storage::get(b"v");
1142 sp_io::storage::get(b"d");
1143 });
1144
1145 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1146 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1147
1148 println!("proof size: {:?}", proof.encoded_size());
1150 println!("compact proof size: {:?}", compact_proof.encoded_size());
1151 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1152
1153 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1155 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1156
1157 let _ = ext.execute_and_prove(|| {
1158 sp_io::storage::set(b"a", &vec![1u8; 44]);
1159 });
1160
1161 ext.execute_with(|| {
1164 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1165 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1166 });
1167 }
1168}
1169
1170#[cfg(test)]
1173mod sp_core_tests {
1174 use super::*;
1175
1176 #[test]
1177 #[should_panic]
1178 fn generate_feature_enabled_macro_panics() {
1179 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1180 if_test!(panic!("This should panic"));
1181 }
1182
1183 #[test]
1184 fn generate_feature_enabled_macro_works() {
1185 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1186 if_not_test!(panic!("This should not panic"));
1187 }
1188}