1#![warn(missing_docs)]
46#![cfg_attr(not(feature = "std"), no_std)]
47
48#[doc(hidden)]
49extern crate alloc;
50
51#[doc(hidden)]
52pub use alloc::vec::Vec;
53#[doc(hidden)]
54pub use codec;
55#[doc(hidden)]
56pub use scale_info;
57#[cfg(feature = "serde")]
58#[doc(hidden)]
59pub use serde;
60#[doc(hidden)]
61pub use sp_std;
62
63#[doc(hidden)]
64pub use paste;
65#[doc(hidden)]
66pub use sp_arithmetic::traits::Saturating;
67
68#[doc(hidden)]
69pub use sp_application_crypto as app_crypto;
70
71pub use sp_core::storage::StateVersion;
72#[cfg(feature = "std")]
73pub use sp_core::storage::{Storage, StorageChild};
74
75use sp_core::{
76 crypto::{self, ByteArray, FromEntropy},
77 ecdsa, ed25519,
78 hash::{H256, H512},
79 sr25519,
80};
81
82use alloc::vec;
83use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
84use scale_info::TypeInfo;
85
86pub mod curve;
87pub mod generic;
88pub mod legacy;
89mod multiaddress;
90pub mod offchain;
91pub mod proving_trie;
92pub mod runtime_logger;
93#[cfg(feature = "std")]
94pub mod testing;
95pub mod traits;
96pub mod transaction_validity;
97pub mod type_with_default;
98
99pub use multiaddress::MultiAddress;
101
102use proving_trie::TrieError;
103
104pub use generic::{Digest, DigestItem};
106
107pub use sp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
108pub use sp_core::{
110 bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec},
111 crypto::{key_types, AccountId32, CryptoType, CryptoTypeId, KeyTypeId},
112 TypeId,
113};
114#[cfg(feature = "std")]
116pub use sp_core::{bounded_btree_map, bounded_vec};
117
118pub use sp_core::RuntimeDebug;
120
121pub use sp_arithmetic::biguint;
123pub use sp_arithmetic::helpers_128bit;
125pub use sp_arithmetic::{
127 traits::SaturatedConversion, ArithmeticError, FixedI128, FixedI64, FixedPointNumber,
128 FixedPointOperand, FixedU128, FixedU64, InnerOf, PerThing, PerU16, Perbill, Percent, Permill,
129 Perquintill, Rational128, Rounding, UpperOf,
130};
131pub use sp_weights::Weight;
133
134pub use either::Either;
135
136pub const MAX_MODULE_ERROR_ENCODED_SIZE: usize = 4;
139
140pub type Justification = (ConsensusEngineId, EncodedJustification);
152
153pub type EncodedJustification = Vec<u8>;
155
156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
159#[derive(Default, Debug, Clone, PartialEq, Eq, Encode, Decode)]
160pub struct Justifications(Vec<Justification>);
161
162impl Justifications {
163 pub fn new(justifications: Vec<Justification>) -> Self {
165 Self(justifications)
166 }
167
168 pub fn iter(&self) -> impl Iterator<Item = &Justification> {
170 self.0.iter()
171 }
172
173 pub fn append(&mut self, justification: Justification) -> bool {
177 if self.get(justification.0).is_some() {
178 return false
179 }
180 self.0.push(justification);
181 true
182 }
183
184 pub fn get(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> {
187 self.iter().find(|j| j.0 == engine_id).map(|j| &j.1)
188 }
189
190 pub fn remove(&mut self, engine_id: ConsensusEngineId) {
192 self.0.retain(|j| j.0 != engine_id)
193 }
194
195 pub fn into_justification(self, engine_id: ConsensusEngineId) -> Option<EncodedJustification> {
198 self.into_iter().find(|j| j.0 == engine_id).map(|j| j.1)
199 }
200}
201
202impl IntoIterator for Justifications {
203 type Item = Justification;
204 type IntoIter = alloc::vec::IntoIter<Self::Item>;
205
206 fn into_iter(self) -> Self::IntoIter {
207 self.0.into_iter()
208 }
209}
210
211impl From<Justification> for Justifications {
212 fn from(justification: Justification) -> Self {
213 Self(vec![justification])
214 }
215}
216
217use traits::{Lazy, Verify};
218
219use crate::traits::{IdentifyAccount, 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,
282 PartialEq,
283 Clone,
284 Encode,
285 Decode,
286 DecodeWithMemTracking,
287 MaxEncodedLen,
288 RuntimeDebug,
289 TypeInfo,
290)]
291pub enum MultiSignature {
292 Ed25519(ed25519::Signature),
294 Sr25519(sr25519::Signature),
296 Ecdsa(ecdsa::Signature),
298 Eth(ecdsa::KeccakSignature),
300}
301
302impl From<ed25519::Signature> for MultiSignature {
303 fn from(x: ed25519::Signature) -> Self {
304 Self::Ed25519(x)
305 }
306}
307
308impl TryFrom<MultiSignature> for ed25519::Signature {
309 type Error = ();
310 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
311 if let MultiSignature::Ed25519(x) = m {
312 Ok(x)
313 } else {
314 Err(())
315 }
316 }
317}
318
319impl From<sr25519::Signature> for MultiSignature {
320 fn from(x: sr25519::Signature) -> Self {
321 Self::Sr25519(x)
322 }
323}
324
325impl TryFrom<MultiSignature> for sr25519::Signature {
326 type Error = ();
327 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
328 if let MultiSignature::Sr25519(x) = m {
329 Ok(x)
330 } else {
331 Err(())
332 }
333 }
334}
335
336impl From<ecdsa::Signature> for MultiSignature {
337 fn from(x: ecdsa::Signature) -> Self {
338 Self::Ecdsa(x)
339 }
340}
341
342impl TryFrom<MultiSignature> for ecdsa::Signature {
343 type Error = ();
344 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
345 if let MultiSignature::Ecdsa(x) = m {
346 Ok(x)
347 } else {
348 Err(())
349 }
350 }
351}
352
353#[derive(
355 Eq,
356 PartialEq,
357 Ord,
358 PartialOrd,
359 Clone,
360 Encode,
361 Decode,
362 DecodeWithMemTracking,
363 RuntimeDebug,
364 TypeInfo,
365)]
366#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
367pub enum MultiSigner {
368 Ed25519(ed25519::Public),
370 Sr25519(sr25519::Public),
372 Ecdsa(ecdsa::Public),
374 Eth(ecdsa::KeccakPublic),
381}
382
383impl FromEntropy for MultiSigner {
384 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
385 Ok(match input.read_byte()? % 4 {
386 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
387 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
388 2 => Self::Ecdsa(FromEntropy::from_entropy(input)?),
389 3.. => Self::Eth(FromEntropy::from_entropy(input)?),
390 })
391 }
392}
393
394impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
397 fn unchecked_from(x: T) -> Self {
398 ed25519::Public::unchecked_from(x.into()).into()
399 }
400}
401
402impl AsRef<[u8]> for MultiSigner {
403 fn as_ref(&self) -> &[u8] {
404 match *self {
405 Self::Ed25519(ref who) => who.as_ref(),
406 Self::Sr25519(ref who) => who.as_ref(),
407 Self::Ecdsa(ref who) => who.as_ref(),
408 Self::Eth(ref who) => who.as_ref(),
409 }
410 }
411}
412
413impl traits::IdentifyAccount for MultiSigner {
414 type AccountId = AccountId32;
415 fn into_account(self) -> AccountId32 {
416 match self {
417 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
418 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
419 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
420 Self::Eth(who) => {
421 let eth_address = &sp_io::hashing::keccak_256(who.as_ref())[12..];
425 let mut address = [0xEE; 32];
428 address[..20].copy_from_slice(eth_address);
429 address.into()
430 },
431 }
432 }
433}
434
435impl From<ed25519::Public> for MultiSigner {
436 fn from(x: ed25519::Public) -> Self {
437 Self::Ed25519(x)
438 }
439}
440
441impl TryFrom<MultiSigner> for ed25519::Public {
442 type Error = ();
443 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
444 if let MultiSigner::Ed25519(x) = m {
445 Ok(x)
446 } else {
447 Err(())
448 }
449 }
450}
451
452impl From<sr25519::Public> for MultiSigner {
453 fn from(x: sr25519::Public) -> Self {
454 Self::Sr25519(x)
455 }
456}
457
458impl TryFrom<MultiSigner> for sr25519::Public {
459 type Error = ();
460 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
461 if let MultiSigner::Sr25519(x) = m {
462 Ok(x)
463 } else {
464 Err(())
465 }
466 }
467}
468
469impl From<ecdsa::Public> for MultiSigner {
470 fn from(x: ecdsa::Public) -> Self {
471 Self::Ecdsa(x)
472 }
473}
474
475impl TryFrom<MultiSigner> for ecdsa::Public {
476 type Error = ();
477 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
478 if let MultiSigner::Ecdsa(x) = m {
479 Ok(x)
480 } else {
481 Err(())
482 }
483 }
484}
485
486#[cfg(feature = "std")]
487impl std::fmt::Display for MultiSigner {
488 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
489 match self {
490 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
491 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
492 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
493 Self::Eth(who) => write!(fmt, "eth: {}", who),
494 }
495 }
496}
497
498impl Verify for MultiSignature {
499 type Signer = MultiSigner;
500 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
501 let who: [u8; 32] = *signer.as_ref();
502 match self {
503 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
504 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
505 Self::Ecdsa(sig) => {
506 let m = sp_io::hashing::blake2_256(msg.get());
507 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
508 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
509 },
510 Self::Eth(sig) => {
511 let m = sp_io::hashing::keccak_256(msg.get());
512 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
513 .map_or(false, |pubkey| {
514 &MultiSigner::Eth(pubkey.into()).into_account() == signer
515 })
516 },
517 }
518 }
519}
520
521#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
524pub struct AnySignature(H512);
525
526impl Verify for AnySignature {
527 type Signer = sr25519::Public;
528 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
529 let msg = msg.get();
530 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
531 .map(|s| s.verify(msg, signer))
532 .unwrap_or(false) ||
533 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
534 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
535 Err(()) => false,
536 Ok(signer) => s.verify(msg, &signer),
537 })
538 .unwrap_or(false)
539 }
540}
541
542impl From<sr25519::Signature> for AnySignature {
543 fn from(s: sr25519::Signature) -> Self {
544 Self(s.into())
545 }
546}
547
548impl From<ed25519::Signature> for AnySignature {
549 fn from(s: ed25519::Signature) -> Self {
550 Self(s.into())
551 }
552}
553
554impl From<DispatchError> for DispatchOutcome {
555 fn from(err: DispatchError) -> Self {
556 Err(err)
557 }
558}
559
560pub type DispatchResult = core::result::Result<(), DispatchError>;
564
565pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
568
569#[derive(
571 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
572)]
573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
574pub struct ModuleError {
575 pub index: u8,
577 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
579 #[codec(skip)]
581 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
582 pub message: Option<&'static str>,
583}
584
585impl PartialEq for ModuleError {
586 fn eq(&self, other: &Self) -> bool {
587 (self.index == other.index) && (self.error == other.error)
588 }
589}
590
591#[derive(
593 Eq,
594 PartialEq,
595 Clone,
596 Copy,
597 Encode,
598 Decode,
599 DecodeWithMemTracking,
600 Debug,
601 TypeInfo,
602 MaxEncodedLen,
603)]
604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
605pub enum TransactionalError {
606 LimitReached,
608 NoLayer,
610}
611
612impl From<TransactionalError> for &'static str {
613 fn from(e: TransactionalError) -> &'static str {
614 match e {
615 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
616 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
617 }
618 }
619}
620
621impl From<TransactionalError> for DispatchError {
622 fn from(e: TransactionalError) -> DispatchError {
623 Self::Transactional(e)
624 }
625}
626
627#[derive(
629 Eq,
630 Clone,
631 Copy,
632 Encode,
633 Decode,
634 DecodeWithMemTracking,
635 Debug,
636 TypeInfo,
637 PartialEq,
638 MaxEncodedLen,
639)]
640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
641pub enum DispatchError {
642 Other(
644 #[codec(skip)]
645 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
646 &'static str,
647 ),
648 CannotLookup,
650 BadOrigin,
652 Module(ModuleError),
654 ConsumerRemaining,
656 NoProviders,
658 TooManyConsumers,
660 Token(TokenError),
662 Arithmetic(ArithmeticError),
664 Transactional(TransactionalError),
667 Exhausted,
669 Corruption,
671 Unavailable,
673 RootNotAllowed,
675 Trie(TrieError),
677}
678
679#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
682pub struct DispatchErrorWithPostInfo<Info>
683where
684 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
685{
686 pub post_info: Info,
688 pub error: DispatchError,
690}
691
692impl DispatchError {
693 pub fn stripped(self) -> Self {
695 match self {
696 DispatchError::Module(ModuleError { index, error, message: Some(_) }) =>
697 DispatchError::Module(ModuleError { index, error, message: None }),
698 m => m,
699 }
700 }
701}
702
703impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
704where
705 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
706 E: Into<DispatchError>,
707{
708 fn from(error: E) -> Self {
709 Self { post_info: Default::default(), error: error.into() }
710 }
711}
712
713impl From<crate::traits::LookupError> for DispatchError {
714 fn from(_: crate::traits::LookupError) -> Self {
715 Self::CannotLookup
716 }
717}
718
719impl From<crate::traits::BadOrigin> for DispatchError {
720 fn from(_: crate::traits::BadOrigin) -> Self {
721 Self::BadOrigin
722 }
723}
724
725#[derive(
727 Eq,
728 PartialEq,
729 Clone,
730 Copy,
731 Encode,
732 Decode,
733 DecodeWithMemTracking,
734 Debug,
735 TypeInfo,
736 MaxEncodedLen,
737)]
738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
739pub enum TokenError {
740 FundsUnavailable,
742 OnlyProvider,
745 BelowMinimum,
747 CannotCreate,
749 UnknownAsset,
751 Frozen,
753 Unsupported,
755 CannotCreateHold,
757 NotExpendable,
759 Blocked,
761}
762
763impl From<TokenError> for &'static str {
764 fn from(e: TokenError) -> &'static str {
765 match e {
766 TokenError::FundsUnavailable => "Funds are unavailable",
767 TokenError::OnlyProvider => "Account that must exist would die",
768 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
769 TokenError::CannotCreate => "Account cannot be created",
770 TokenError::UnknownAsset => "The asset in question is unknown",
771 TokenError::Frozen => "Funds exist but are frozen",
772 TokenError::Unsupported => "Operation is not supported by the asset",
773 TokenError::CannotCreateHold =>
774 "Account cannot be created for recording amount on hold",
775 TokenError::NotExpendable => "Account that is desired to remain would die",
776 TokenError::Blocked => "Account cannot receive the assets",
777 }
778 }
779}
780
781impl From<TokenError> for DispatchError {
782 fn from(e: TokenError) -> DispatchError {
783 Self::Token(e)
784 }
785}
786
787impl From<ArithmeticError> for DispatchError {
788 fn from(e: ArithmeticError) -> DispatchError {
789 Self::Arithmetic(e)
790 }
791}
792
793impl From<TrieError> for DispatchError {
794 fn from(e: TrieError) -> DispatchError {
795 Self::Trie(e)
796 }
797}
798
799impl From<&'static str> for DispatchError {
800 fn from(err: &'static str) -> DispatchError {
801 Self::Other(err)
802 }
803}
804
805impl From<DispatchError> for &'static str {
806 fn from(err: DispatchError) -> &'static str {
807 use DispatchError::*;
808 match err {
809 Other(msg) => msg,
810 CannotLookup => "Cannot lookup",
811 BadOrigin => "Bad origin",
812 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
813 ConsumerRemaining => "Consumer remaining",
814 NoProviders => "No providers",
815 TooManyConsumers => "Too many consumers",
816 Token(e) => e.into(),
817 Arithmetic(e) => e.into(),
818 Transactional(e) => e.into(),
819 Exhausted => "Resources exhausted",
820 Corruption => "State corrupt",
821 Unavailable => "Resource unavailable",
822 RootNotAllowed => "Root not allowed",
823 Trie(e) => e.into(),
824 }
825 }
826}
827
828impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
829where
830 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
831{
832 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
833 err.error.into()
834 }
835}
836
837impl traits::Printable for DispatchError {
838 fn print(&self) {
839 use DispatchError::*;
840 "DispatchError".print();
841 match self {
842 Other(err) => err.print(),
843 CannotLookup => "Cannot lookup".print(),
844 BadOrigin => "Bad origin".print(),
845 Module(ModuleError { index, error, message }) => {
846 index.print();
847 error.print();
848 if let Some(msg) = message {
849 msg.print();
850 }
851 },
852 ConsumerRemaining => "Consumer remaining".print(),
853 NoProviders => "No providers".print(),
854 TooManyConsumers => "Too many consumers".print(),
855 Token(e) => {
856 "Token error: ".print();
857 <&'static str>::from(*e).print();
858 },
859 Arithmetic(e) => {
860 "Arithmetic error: ".print();
861 <&'static str>::from(*e).print();
862 },
863 Transactional(e) => {
864 "Transactional error: ".print();
865 <&'static str>::from(*e).print();
866 },
867 Exhausted => "Resources exhausted".print(),
868 Corruption => "State corrupt".print(),
869 Unavailable => "Resource unavailable".print(),
870 RootNotAllowed => "Root not allowed".print(),
871 Trie(e) => {
872 "Trie error: ".print();
873 <&'static str>::from(*e).print();
874 },
875 }
876 }
877}
878
879impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
880where
881 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
882{
883 fn print(&self) {
884 self.error.print();
885 "PostInfo: ".print();
886 self.post_info.print();
887 }
888}
889
890pub type DispatchOutcome = Result<(), DispatchError>;
900
901pub type ApplyExtrinsicResult =
920 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
921
922pub type ApplyExtrinsicResultWithInfo<T> =
924 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
925
926pub type TryRuntimeError = DispatchError;
928
929pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
932 sig: &V,
933 item: &T,
934 signer: &<V::Signer as IdentifyAccount>::AccountId,
935) -> bool {
936 struct LazyEncode<F> {
941 inner: F,
942 encoded: Option<Vec<u8>>,
943 }
944
945 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
946 fn get(&mut self) -> &[u8] {
947 self.encoded.get_or_insert_with(&self.inner).as_slice()
948 }
949 }
950
951 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
952}
953
954#[macro_export]
972#[cfg(feature = "std")]
973macro_rules! assert_eq_error_rate {
974 ($x:expr, $y:expr, $error:expr $(,)?) => {
975 assert!(
976 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
977 ($x <= $crate::Saturating::saturating_add($y, $error)),
978 "{:?} != {:?} (with error rate {:?})",
979 $x,
980 $y,
981 $error,
982 );
983 };
984}
985
986#[macro_export]
989#[cfg(feature = "std")]
990macro_rules! assert_eq_error_rate_float {
991 ($x:expr, $y:expr, $error:expr $(,)?) => {
992 assert!(
993 ($x >= $y - $error) && ($x <= $y + $error),
994 "{:?} != {:?} (with error rate {:?})",
995 $x,
996 $y,
997 $error,
998 );
999 };
1000}
1001
1002#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
1005pub struct OpaqueExtrinsic(bytes::Bytes);
1006
1007impl TypeInfo for OpaqueExtrinsic {
1008 type Identity = Self;
1009 fn type_info() -> scale_info::Type {
1010 scale_info::Type::builder()
1011 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
1012 .composite(
1013 scale_info::build::Fields::unnamed()
1014 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
1015 )
1016 }
1017}
1018
1019impl OpaqueExtrinsic {
1020 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1022 Self::decode(&mut bytes)
1023 }
1024
1025 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
1027 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
1028 Self::try_from_encoded_extrinsic(bytes)
1029 }
1030
1031 pub fn from_blob(bytes: Vec<u8>) -> Self {
1033 Self(bytes.into())
1034 }
1035
1036 pub fn inner(&self) -> &[u8] {
1038 &self.0
1039 }
1040}
1041
1042impl LazyExtrinsic for OpaqueExtrinsic {
1043 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
1044 Ok(Self(data.to_vec().into()))
1045 }
1046}
1047
1048impl core::fmt::Debug for OpaqueExtrinsic {
1049 #[cfg(feature = "std")]
1050 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1051 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1052 }
1053
1054 #[cfg(not(feature = "std"))]
1055 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1056 Ok(())
1057 }
1058}
1059
1060#[cfg(feature = "serde")]
1061impl ::serde::Serialize for OpaqueExtrinsic {
1062 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1063 where
1064 S: ::serde::Serializer,
1065 {
1066 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1067 }
1068}
1069
1070#[cfg(feature = "serde")]
1071impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1072 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1073 where
1074 D: ::serde::Deserializer<'a>,
1075 {
1076 let r = ::sp_core::bytes::deserialize(de)?;
1077 Decode::decode(&mut &r[..])
1078 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1079 }
1080}
1081
1082impl traits::ExtrinsicLike for OpaqueExtrinsic {
1083 fn is_bare(&self) -> bool {
1084 false
1085 }
1086}
1087
1088pub fn print(print: impl traits::Printable) {
1090 print.print();
1091}
1092
1093pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1108 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1109 let mut i = 0;
1110 let mut arr = [0; N];
1111 let s = s.as_bytes();
1112 while i < s.len() {
1113 arr[i] = s[i];
1114 i += 1;
1115 }
1116 arr
1117}
1118
1119pub enum TransactionOutcome<R> {
1121 Commit(R),
1123 Rollback(R),
1125}
1126
1127impl<R> TransactionOutcome<R> {
1128 pub fn into_inner(self) -> R {
1130 match self {
1131 Self::Commit(r) => r,
1132 Self::Rollback(r) => r,
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1139pub enum ExtrinsicInclusionMode {
1140 #[default]
1142 AllExtrinsics,
1143 OnlyInherents,
1145}
1146
1147#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
1149pub struct OpaqueValue(Vec<u8>);
1150impl OpaqueValue {
1151 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1153 OpaqueValue(inner)
1154 }
1155
1156 pub fn decode<T: Decode>(&self) -> Option<T> {
1158 Decode::decode(&mut &self.0[..]).ok()
1159 }
1160}
1161
1162#[macro_export]
1165#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1166macro_rules! create_runtime_str {
1167 ( $y:expr ) => {{
1168 $crate::Cow::Borrowed($y)
1169 }};
1170}
1171#[doc(hidden)]
1173pub use alloc::borrow::Cow;
1174
1175#[deprecated = "Use String or Cow<'static, str> instead"]
1178pub type RuntimeString = alloc::string::String;
1179
1180#[cfg(test)]
1181mod tests {
1182 use crate::traits::BlakeTwo256;
1183
1184 use super::*;
1185 use codec::{Decode, Encode};
1186 use sp_core::{crypto::Pair, hex2array};
1187 use sp_io::TestExternalities;
1188 use sp_state_machine::create_proof_check_backend;
1189
1190 #[test]
1191 fn opaque_extrinsic_serialization() {
1192 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1193 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1194 }
1195
1196 #[test]
1197 fn dispatch_error_encoding() {
1198 let error = DispatchError::Module(ModuleError {
1199 index: 1,
1200 error: [2, 0, 0, 0],
1201 message: Some("error message"),
1202 });
1203 let encoded = error.encode();
1204 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1205 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1206 assert_eq!(
1207 decoded,
1208 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1209 );
1210 }
1211
1212 #[test]
1213 fn dispatch_error_equality() {
1214 use DispatchError::*;
1215
1216 let variants = vec![
1217 Other("foo"),
1218 Other("bar"),
1219 CannotLookup,
1220 BadOrigin,
1221 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1222 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1223 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1224 ConsumerRemaining,
1225 NoProviders,
1226 Token(TokenError::FundsUnavailable),
1227 Token(TokenError::OnlyProvider),
1228 Token(TokenError::BelowMinimum),
1229 Token(TokenError::CannotCreate),
1230 Token(TokenError::UnknownAsset),
1231 Token(TokenError::Frozen),
1232 Arithmetic(ArithmeticError::Overflow),
1233 Arithmetic(ArithmeticError::Underflow),
1234 Arithmetic(ArithmeticError::DivisionByZero),
1235 ];
1236 for (i, variant) in variants.iter().enumerate() {
1237 for (j, other_variant) in variants.iter().enumerate() {
1238 if i == j {
1239 assert_eq!(variant, other_variant);
1240 } else {
1241 assert_ne!(variant, other_variant);
1242 }
1243 }
1244 }
1245
1246 assert_eq!(
1248 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1249 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1250 );
1251 }
1252
1253 #[test]
1254 fn multi_signature_ecdsa_verify_works() {
1255 let msg = &b"test-message"[..];
1256 let (pair, _) = ecdsa::Pair::generate();
1257
1258 let signature = pair.sign(&msg);
1259 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1260
1261 let multi_sig = MultiSignature::from(signature);
1262 let multi_signer = MultiSigner::from(pair.public());
1263 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1264 }
1265
1266 #[test]
1267 fn multi_signature_eth_verify_works() {
1268 let msg = &b"test-message"[..];
1269 let (pair, _) = ecdsa::KeccakPair::generate();
1270
1271 let signature = pair.sign(&msg);
1272 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1273
1274 let multi_sig = MultiSignature::Eth(signature);
1275 let multi_signer = MultiSigner::Eth(pair.public());
1276 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1277 }
1278
1279 #[test]
1280 fn multi_signer_eth_address_works() {
1281 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1282 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1283 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1284 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1285
1286 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1287 assert_eq!(
1288 ecdsa,
1289 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1290 );
1291 assert_eq!(
1292 eth,
1293 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1294 );
1295 }
1296
1297 #[test]
1298 fn execute_and_generate_proof_works() {
1299 use codec::Encode;
1300 use sp_state_machine::Backend;
1301 let mut ext = TestExternalities::default();
1302
1303 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1304 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1305 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1306 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1307
1308 let pre_root = *ext.backend.root();
1309 let (_, proof) = ext.execute_and_prove(|| {
1310 sp_io::storage::get(b"a");
1311 sp_io::storage::get(b"b");
1312 sp_io::storage::get(b"v");
1313 sp_io::storage::get(b"d");
1314 });
1315
1316 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1317 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1318
1319 println!("proof size: {:?}", proof.encoded_size());
1321 println!("compact proof size: {:?}", compact_proof.encoded_size());
1322 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1323
1324 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1326 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1327
1328 let _ = ext.execute_and_prove(|| {
1329 sp_io::storage::set(b"a", &vec![1u8; 44]);
1330 });
1331
1332 ext.execute_with(|| {
1335 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1336 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1337 });
1338 }
1339}
1340
1341#[cfg(test)]
1344mod sp_core_tests {
1345 use super::*;
1346
1347 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1348 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1349
1350 #[test]
1351 #[should_panic]
1352 fn generate_feature_enabled_macro_panics() {
1353 if_test!(panic!("This should panic"));
1354 }
1355
1356 #[test]
1357 fn generate_feature_enabled_macro_works() {
1358 if_not_test!(panic!("This should not panic"));
1359 }
1360}