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 core::fmt::Debug;
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, LazyExtrinsic};
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, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, Debug, TypeInfo,
282)]
283pub enum MultiSignature {
284 Ed25519(ed25519::Signature),
286 Sr25519(sr25519::Signature),
288 Ecdsa(ecdsa::Signature),
290 Eth(ecdsa::KeccakSignature),
292}
293
294impl From<ed25519::Signature> for MultiSignature {
295 fn from(x: ed25519::Signature) -> Self {
296 Self::Ed25519(x)
297 }
298}
299
300impl TryFrom<MultiSignature> for ed25519::Signature {
301 type Error = ();
302 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
303 if let MultiSignature::Ed25519(x) = m {
304 Ok(x)
305 } else {
306 Err(())
307 }
308 }
309}
310
311impl From<sr25519::Signature> for MultiSignature {
312 fn from(x: sr25519::Signature) -> Self {
313 Self::Sr25519(x)
314 }
315}
316
317impl TryFrom<MultiSignature> for sr25519::Signature {
318 type Error = ();
319 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
320 if let MultiSignature::Sr25519(x) = m {
321 Ok(x)
322 } else {
323 Err(())
324 }
325 }
326}
327
328impl From<ecdsa::Signature> for MultiSignature {
329 fn from(x: ecdsa::Signature) -> Self {
330 Self::Ecdsa(x)
331 }
332}
333
334impl TryFrom<MultiSignature> for ecdsa::Signature {
335 type Error = ();
336 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
337 if let MultiSignature::Ecdsa(x) = m {
338 Ok(x)
339 } else {
340 Err(())
341 }
342 }
343}
344
345#[derive(
347 Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo,
348)]
349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
350pub enum MultiSigner {
351 Ed25519(ed25519::Public),
353 Sr25519(sr25519::Public),
355 Ecdsa(ecdsa::Public),
357 Eth(ecdsa::KeccakPublic),
364}
365
366impl FromEntropy for MultiSigner {
367 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
368 Ok(match input.read_byte()? % 4 {
369 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
370 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
371 2 => Self::Ecdsa(FromEntropy::from_entropy(input)?),
372 3.. => Self::Eth(FromEntropy::from_entropy(input)?),
373 })
374 }
375}
376
377impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
380 fn unchecked_from(x: T) -> Self {
381 ed25519::Public::unchecked_from(x.into()).into()
382 }
383}
384
385impl AsRef<[u8]> for MultiSigner {
386 fn as_ref(&self) -> &[u8] {
387 match *self {
388 Self::Ed25519(ref who) => who.as_ref(),
389 Self::Sr25519(ref who) => who.as_ref(),
390 Self::Ecdsa(ref who) => who.as_ref(),
391 Self::Eth(ref who) => who.as_ref(),
392 }
393 }
394}
395
396impl traits::IdentifyAccount for MultiSigner {
397 type AccountId = AccountId32;
398 fn into_account(self) -> AccountId32 {
399 match self {
400 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
401 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
402 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
403 Self::Eth(who) => {
404 let eth_address = &sp_io::hashing::keccak_256(who.as_ref())[12..];
408 let mut address = [0xEE; 32];
411 address[..20].copy_from_slice(eth_address);
412 address.into()
413 },
414 }
415 }
416}
417
418impl From<ed25519::Public> for MultiSigner {
419 fn from(x: ed25519::Public) -> Self {
420 Self::Ed25519(x)
421 }
422}
423
424impl TryFrom<MultiSigner> for ed25519::Public {
425 type Error = ();
426 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
427 if let MultiSigner::Ed25519(x) = m {
428 Ok(x)
429 } else {
430 Err(())
431 }
432 }
433}
434
435impl From<sr25519::Public> for MultiSigner {
436 fn from(x: sr25519::Public) -> Self {
437 Self::Sr25519(x)
438 }
439}
440
441impl TryFrom<MultiSigner> for sr25519::Public {
442 type Error = ();
443 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
444 if let MultiSigner::Sr25519(x) = m {
445 Ok(x)
446 } else {
447 Err(())
448 }
449 }
450}
451
452impl From<ecdsa::Public> for MultiSigner {
453 fn from(x: ecdsa::Public) -> Self {
454 Self::Ecdsa(x)
455 }
456}
457
458impl TryFrom<MultiSigner> for ecdsa::Public {
459 type Error = ();
460 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
461 if let MultiSigner::Ecdsa(x) = m {
462 Ok(x)
463 } else {
464 Err(())
465 }
466 }
467}
468
469#[cfg(feature = "std")]
470impl std::fmt::Display for MultiSigner {
471 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
472 match self {
473 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
474 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
475 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
476 Self::Eth(who) => write!(fmt, "eth: {}", who),
477 }
478 }
479}
480
481impl Verify for MultiSignature {
482 type Signer = MultiSigner;
483 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
484 let who: [u8; 32] = *signer.as_ref();
485 match self {
486 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
487 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
488 Self::Ecdsa(sig) => {
489 let m = sp_io::hashing::blake2_256(msg.get());
490 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
491 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
492 },
493 Self::Eth(sig) => {
494 let m = sp_io::hashing::keccak_256(msg.get());
495 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
496 .map_or(false, |pubkey| {
497 &MultiSigner::Eth(pubkey.into()).into_account() == signer
498 })
499 },
500 }
501 }
502}
503
504#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, Debug, TypeInfo)]
506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
507pub struct AnySignature(H512);
508
509impl Verify for AnySignature {
510 type Signer = sr25519::Public;
511 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
512 let msg = msg.get();
513 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
514 .map(|s| s.verify(msg, signer))
515 .unwrap_or(false) ||
516 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
517 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
518 Err(()) => false,
519 Ok(signer) => s.verify(msg, &signer),
520 })
521 .unwrap_or(false)
522 }
523}
524
525impl From<sr25519::Signature> for AnySignature {
526 fn from(s: sr25519::Signature) -> Self {
527 Self(s.into())
528 }
529}
530
531impl From<ed25519::Signature> for AnySignature {
532 fn from(s: ed25519::Signature) -> Self {
533 Self(s.into())
534 }
535}
536
537impl From<DispatchError> for DispatchOutcome {
538 fn from(err: DispatchError) -> Self {
539 Err(err)
540 }
541}
542
543pub type DispatchResult = core::result::Result<(), DispatchError>;
547
548pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
551
552#[derive(
554 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
555)]
556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
557pub struct ModuleError {
558 pub index: u8,
560 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
562 #[codec(skip)]
564 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
565 pub message: Option<&'static str>,
566}
567
568impl PartialEq for ModuleError {
569 fn eq(&self, other: &Self) -> bool {
570 (self.index == other.index) && (self.error == other.error)
571 }
572}
573
574#[derive(
576 Eq,
577 PartialEq,
578 Clone,
579 Copy,
580 Encode,
581 Decode,
582 DecodeWithMemTracking,
583 Debug,
584 TypeInfo,
585 MaxEncodedLen,
586)]
587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
588pub enum TransactionalError {
589 LimitReached,
591 NoLayer,
593}
594
595impl From<TransactionalError> for &'static str {
596 fn from(e: TransactionalError) -> &'static str {
597 match e {
598 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
599 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
600 }
601 }
602}
603
604impl From<TransactionalError> for DispatchError {
605 fn from(e: TransactionalError) -> DispatchError {
606 Self::Transactional(e)
607 }
608}
609
610#[derive(
612 Eq,
613 Clone,
614 Copy,
615 Encode,
616 Decode,
617 DecodeWithMemTracking,
618 Debug,
619 TypeInfo,
620 PartialEq,
621 MaxEncodedLen,
622)]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624pub enum DispatchError {
625 Other(
627 #[codec(skip)]
628 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
629 &'static str,
630 ),
631 CannotLookup,
633 BadOrigin,
635 Module(ModuleError),
637 ConsumerRemaining,
639 NoProviders,
641 TooManyConsumers,
643 Token(TokenError),
645 Arithmetic(ArithmeticError),
647 Transactional(TransactionalError),
650 Exhausted,
652 Corruption,
654 Unavailable,
656 RootNotAllowed,
658 Trie(TrieError),
660}
661
662#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
665pub struct DispatchErrorWithPostInfo<Info>
666where
667 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
668{
669 pub post_info: Info,
671 pub error: DispatchError,
673}
674
675impl DispatchError {
676 pub fn stripped(self) -> Self {
678 match self {
679 DispatchError::Module(ModuleError { index, error, message: Some(_) }) => {
680 DispatchError::Module(ModuleError { index, error, message: None })
681 },
682 m => m,
683 }
684 }
685}
686
687impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
688where
689 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
690 E: Into<DispatchError>,
691{
692 fn from(error: E) -> Self {
693 Self { post_info: Default::default(), error: error.into() }
694 }
695}
696
697impl From<crate::traits::LookupError> for DispatchError {
698 fn from(_: crate::traits::LookupError) -> Self {
699 Self::CannotLookup
700 }
701}
702
703impl From<crate::traits::BadOrigin> for DispatchError {
704 fn from(_: crate::traits::BadOrigin) -> Self {
705 Self::BadOrigin
706 }
707}
708
709#[derive(
711 Eq,
712 PartialEq,
713 Clone,
714 Copy,
715 Encode,
716 Decode,
717 DecodeWithMemTracking,
718 Debug,
719 TypeInfo,
720 MaxEncodedLen,
721)]
722#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
723pub enum TokenError {
724 FundsUnavailable,
726 OnlyProvider,
729 BelowMinimum,
731 CannotCreate,
733 UnknownAsset,
735 Frozen,
737 Unsupported,
739 CannotCreateHold,
741 NotExpendable,
743 Blocked,
745}
746
747impl From<TokenError> for &'static str {
748 fn from(e: TokenError) -> &'static str {
749 match e {
750 TokenError::FundsUnavailable => "Funds are unavailable",
751 TokenError::OnlyProvider => "Account that must exist would die",
752 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
753 TokenError::CannotCreate => "Account cannot be created",
754 TokenError::UnknownAsset => "The asset in question is unknown",
755 TokenError::Frozen => "Funds exist but are frozen",
756 TokenError::Unsupported => "Operation is not supported by the asset",
757 TokenError::CannotCreateHold => {
758 "Account cannot be created for recording amount on hold"
759 },
760 TokenError::NotExpendable => "Account that is desired to remain would die",
761 TokenError::Blocked => "Account cannot receive the assets",
762 }
763 }
764}
765
766impl From<TokenError> for DispatchError {
767 fn from(e: TokenError) -> DispatchError {
768 Self::Token(e)
769 }
770}
771
772impl From<ArithmeticError> for DispatchError {
773 fn from(e: ArithmeticError) -> DispatchError {
774 Self::Arithmetic(e)
775 }
776}
777
778impl From<TrieError> for DispatchError {
779 fn from(e: TrieError) -> DispatchError {
780 Self::Trie(e)
781 }
782}
783
784impl From<&'static str> for DispatchError {
785 fn from(err: &'static str) -> DispatchError {
786 Self::Other(err)
787 }
788}
789
790impl From<DispatchError> for &'static str {
791 fn from(err: DispatchError) -> &'static str {
792 use DispatchError::*;
793 match err {
794 Other(msg) => msg,
795 CannotLookup => "Cannot lookup",
796 BadOrigin => "Bad origin",
797 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
798 ConsumerRemaining => "Consumer remaining",
799 NoProviders => "No providers",
800 TooManyConsumers => "Too many consumers",
801 Token(e) => e.into(),
802 Arithmetic(e) => e.into(),
803 Transactional(e) => e.into(),
804 Exhausted => "Resources exhausted",
805 Corruption => "State corrupt",
806 Unavailable => "Resource unavailable",
807 RootNotAllowed => "Root not allowed",
808 Trie(e) => e.into(),
809 }
810 }
811}
812
813impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
814where
815 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
816{
817 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
818 err.error.into()
819 }
820}
821
822impl traits::Printable for DispatchError {
823 fn print(&self) {
824 use DispatchError::*;
825 "DispatchError".print();
826 match self {
827 Other(err) => err.print(),
828 CannotLookup => "Cannot lookup".print(),
829 BadOrigin => "Bad origin".print(),
830 Module(ModuleError { index, error, message }) => {
831 index.print();
832 error.print();
833 if let Some(msg) = message {
834 msg.print();
835 }
836 },
837 ConsumerRemaining => "Consumer remaining".print(),
838 NoProviders => "No providers".print(),
839 TooManyConsumers => "Too many consumers".print(),
840 Token(e) => {
841 "Token error: ".print();
842 <&'static str>::from(*e).print();
843 },
844 Arithmetic(e) => {
845 "Arithmetic error: ".print();
846 <&'static str>::from(*e).print();
847 },
848 Transactional(e) => {
849 "Transactional error: ".print();
850 <&'static str>::from(*e).print();
851 },
852 Exhausted => "Resources exhausted".print(),
853 Corruption => "State corrupt".print(),
854 Unavailable => "Resource unavailable".print(),
855 RootNotAllowed => "Root not allowed".print(),
856 Trie(e) => {
857 "Trie error: ".print();
858 <&'static str>::from(*e).print();
859 },
860 }
861 }
862}
863
864impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
865where
866 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
867{
868 fn print(&self) {
869 self.error.print();
870 "PostInfo: ".print();
871 self.post_info.print();
872 }
873}
874
875pub type DispatchOutcome = Result<(), DispatchError>;
885
886pub type ApplyExtrinsicResult =
905 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
906
907pub type ApplyExtrinsicResultWithInfo<T> =
909 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
910
911pub type TryRuntimeError = DispatchError;
913
914pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
917 sig: &V,
918 item: &T,
919 signer: &<V::Signer as IdentifyAccount>::AccountId,
920) -> bool {
921 struct LazyEncode<F> {
926 inner: F,
927 encoded: Option<Vec<u8>>,
928 }
929
930 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
931 fn get(&mut self) -> &[u8] {
932 self.encoded.get_or_insert_with(&self.inner).as_slice()
933 }
934 }
935
936 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
937}
938
939#[macro_export]
957#[cfg(feature = "std")]
958macro_rules! assert_eq_error_rate {
959 ($x:expr, $y:expr, $error:expr $(,)?) => {
960 assert!(
961 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
962 ($x <= $crate::Saturating::saturating_add($y, $error)),
963 "{:?} != {:?} (with error rate {:?})",
964 $x,
965 $y,
966 $error,
967 );
968 };
969}
970
971#[macro_export]
974#[cfg(feature = "std")]
975macro_rules! assert_eq_error_rate_float {
976 ($x:expr, $y:expr, $error:expr $(,)?) => {
977 assert!(
978 ($x >= $y - $error) && ($x <= $y + $error),
979 "{:?} != {:?} (with error rate {:?})",
980 $x,
981 $y,
982 $error,
983 );
984 };
985}
986
987#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
990pub struct OpaqueExtrinsic(bytes::Bytes);
991
992impl TypeInfo for OpaqueExtrinsic {
993 type Identity = Self;
994 fn type_info() -> scale_info::Type {
995 scale_info::Type::builder()
996 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
997 .composite(
998 scale_info::build::Fields::unnamed()
999 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
1000 )
1001 }
1002}
1003
1004impl OpaqueExtrinsic {
1005 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1007 Self::decode(&mut bytes)
1008 }
1009
1010 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
1012 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
1013 Self::try_from_encoded_extrinsic(bytes)
1014 }
1015
1016 pub fn from_blob(bytes: Vec<u8>) -> Self {
1018 Self(bytes.into())
1019 }
1020
1021 pub fn inner(&self) -> &[u8] {
1023 &self.0
1024 }
1025}
1026
1027impl LazyExtrinsic for OpaqueExtrinsic {
1028 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
1029 Ok(Self(data.to_vec().into()))
1030 }
1031}
1032
1033impl core::fmt::Debug for OpaqueExtrinsic {
1034 #[cfg(feature = "std")]
1035 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1036 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1037 }
1038
1039 #[cfg(not(feature = "std"))]
1040 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1041 Ok(())
1042 }
1043}
1044
1045#[cfg(feature = "serde")]
1046impl ::serde::Serialize for OpaqueExtrinsic {
1047 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1048 where
1049 S: ::serde::Serializer,
1050 {
1051 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1052 }
1053}
1054
1055#[cfg(feature = "serde")]
1056impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1057 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1058 where
1059 D: ::serde::Deserializer<'a>,
1060 {
1061 let r = ::sp_core::bytes::deserialize(de)?;
1062 Decode::decode(&mut &r[..])
1063 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1064 }
1065}
1066
1067impl traits::ExtrinsicLike for OpaqueExtrinsic {
1068 fn is_bare(&self) -> bool {
1069 false
1070 }
1071}
1072
1073pub fn print(print: impl traits::Printable) {
1075 print.print();
1076}
1077
1078pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1093 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1094 let mut i = 0;
1095 let mut arr = [0; N];
1096 let s = s.as_bytes();
1097 while i < s.len() {
1098 arr[i] = s[i];
1099 i += 1;
1100 }
1101 arr
1102}
1103
1104pub enum TransactionOutcome<R> {
1106 Commit(R),
1108 Rollback(R),
1110}
1111
1112impl<R> TransactionOutcome<R> {
1113 pub fn into_inner(self) -> R {
1115 match self {
1116 Self::Commit(r) => r,
1117 Self::Rollback(r) => r,
1118 }
1119 }
1120}
1121
1122#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1124pub enum ExtrinsicInclusionMode {
1125 #[default]
1127 AllExtrinsics,
1128 OnlyInherents,
1130}
1131
1132#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
1134pub struct OpaqueValue(Vec<u8>);
1135impl OpaqueValue {
1136 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1138 OpaqueValue(inner)
1139 }
1140
1141 pub fn decode<T: Decode>(&self) -> Option<T> {
1143 Decode::decode(&mut &self.0[..]).ok()
1144 }
1145}
1146
1147#[macro_export]
1150#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1151macro_rules! create_runtime_str {
1152 ( $y:expr ) => {{
1153 $crate::Cow::Borrowed($y)
1154 }};
1155}
1156#[doc(hidden)]
1158pub use alloc::borrow::Cow;
1159
1160#[deprecated = "Use String or Cow<'static, str> instead"]
1163pub type RuntimeString = alloc::string::String;
1164
1165#[cfg(test)]
1166mod tests {
1167 use crate::traits::BlakeTwo256;
1168
1169 use super::*;
1170 use codec::{Decode, Encode};
1171 use sp_core::{crypto::Pair, hex2array};
1172 use sp_io::TestExternalities;
1173 use sp_state_machine::create_proof_check_backend;
1174
1175 #[test]
1176 fn opaque_extrinsic_serialization() {
1177 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1178 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1179 }
1180
1181 #[test]
1182 fn dispatch_error_encoding() {
1183 let error = DispatchError::Module(ModuleError {
1184 index: 1,
1185 error: [2, 0, 0, 0],
1186 message: Some("error message"),
1187 });
1188 let encoded = error.encode();
1189 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1190 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1191 assert_eq!(
1192 decoded,
1193 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1194 );
1195 }
1196
1197 #[test]
1198 fn dispatch_error_equality() {
1199 use DispatchError::*;
1200
1201 let variants = vec![
1202 Other("foo"),
1203 Other("bar"),
1204 CannotLookup,
1205 BadOrigin,
1206 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1207 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1208 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1209 ConsumerRemaining,
1210 NoProviders,
1211 Token(TokenError::FundsUnavailable),
1212 Token(TokenError::OnlyProvider),
1213 Token(TokenError::BelowMinimum),
1214 Token(TokenError::CannotCreate),
1215 Token(TokenError::UnknownAsset),
1216 Token(TokenError::Frozen),
1217 Arithmetic(ArithmeticError::Overflow),
1218 Arithmetic(ArithmeticError::Underflow),
1219 Arithmetic(ArithmeticError::DivisionByZero),
1220 ];
1221 for (i, variant) in variants.iter().enumerate() {
1222 for (j, other_variant) in variants.iter().enumerate() {
1223 if i == j {
1224 assert_eq!(variant, other_variant);
1225 } else {
1226 assert_ne!(variant, other_variant);
1227 }
1228 }
1229 }
1230
1231 assert_eq!(
1233 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1234 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1235 );
1236 }
1237
1238 #[test]
1239 fn multi_signature_ecdsa_verify_works() {
1240 let msg = &b"test-message"[..];
1241 let (pair, _) = ecdsa::Pair::generate();
1242
1243 let signature = pair.sign(&msg);
1244 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1245
1246 let multi_sig = MultiSignature::from(signature);
1247 let multi_signer = MultiSigner::from(pair.public());
1248 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1249 }
1250
1251 #[test]
1252 fn multi_signature_eth_verify_works() {
1253 let msg = &b"test-message"[..];
1254 let (pair, _) = ecdsa::KeccakPair::generate();
1255
1256 let signature = pair.sign(&msg);
1257 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1258
1259 let multi_sig = MultiSignature::Eth(signature);
1260 let multi_signer = MultiSigner::Eth(pair.public());
1261 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1262 }
1263
1264 #[test]
1265 fn multi_signer_eth_address_works() {
1266 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1267 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1268 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1269 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1270
1271 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1272 assert_eq!(
1273 ecdsa,
1274 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1275 );
1276 assert_eq!(
1277 eth,
1278 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1279 );
1280 }
1281
1282 #[test]
1283 fn execute_and_generate_proof_works() {
1284 use codec::Encode;
1285 use sp_state_machine::Backend;
1286 let mut ext = TestExternalities::default();
1287
1288 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1289 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1290 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1291 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1292
1293 let pre_root = *ext.backend.root();
1294 let (_, proof) = ext.execute_and_prove(|| {
1295 sp_io::storage::get(b"a");
1296 sp_io::storage::get(b"b");
1297 sp_io::storage::get(b"v");
1298 sp_io::storage::get(b"d");
1299 });
1300
1301 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1302 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1303
1304 println!("proof size: {:?}", proof.encoded_size());
1306 println!("compact proof size: {:?}", compact_proof.encoded_size());
1307 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1308
1309 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1311 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1312
1313 let _ = ext.execute_and_prove(|| {
1314 sp_io::storage::set(b"a", &vec![1u8; 44]);
1315 });
1316
1317 ext.execute_with(|| {
1320 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1321 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1322 });
1323 }
1324}
1325
1326#[cfg(test)]
1329mod sp_core_tests {
1330 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1331 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1332
1333 #[test]
1334 #[should_panic]
1335 fn generate_feature_enabled_macro_panics() {
1336 if_test!(panic!("This should panic"));
1337 }
1338
1339 #[test]
1340 fn generate_feature_enabled_macro_works() {
1341 if_not_test!(panic!("This should not panic"));
1342 }
1343}