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")]
237impl BuildStorage for sp_core::storage::Storage {
238 fn assimilate_storage(&self, storage: &mut sp_core::storage::Storage) -> Result<(), String> {
239 storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone())));
240 for (k, other_map) in self.children_default.iter() {
241 let k = k.clone();
242 if let Some(map) = storage.children_default.get_mut(&k) {
243 map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone())));
244 if !map.child_info.try_update(&other_map.child_info) {
245 return Err("Incompatible child info update".to_string());
246 }
247 } else {
248 storage.children_default.insert(k, other_map.clone());
249 }
250 }
251 Ok(())
252 }
253}
254
255#[cfg(feature = "std")]
256impl BuildStorage for () {
257 fn assimilate_storage(&self, _: &mut sp_core::storage::Storage) -> Result<(), String> {
258 Err("`assimilate_storage` not implemented for `()`".into())
259 }
260}
261
262pub type ConsensusEngineId = [u8; 4];
264
265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
267#[derive(
268 Eq, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, Debug, TypeInfo,
269)]
270pub enum MultiSignature {
271 Ed25519(ed25519::Signature),
273 Sr25519(sr25519::Signature),
275 Ecdsa(ecdsa::Signature),
277 Eth(ecdsa::KeccakSignature),
279}
280
281impl From<ed25519::Signature> for MultiSignature {
282 fn from(x: ed25519::Signature) -> Self {
283 Self::Ed25519(x)
284 }
285}
286
287impl TryFrom<MultiSignature> for ed25519::Signature {
288 type Error = ();
289 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
290 if let MultiSignature::Ed25519(x) = m {
291 Ok(x)
292 } else {
293 Err(())
294 }
295 }
296}
297
298impl From<sr25519::Signature> for MultiSignature {
299 fn from(x: sr25519::Signature) -> Self {
300 Self::Sr25519(x)
301 }
302}
303
304impl TryFrom<MultiSignature> for sr25519::Signature {
305 type Error = ();
306 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
307 if let MultiSignature::Sr25519(x) = m {
308 Ok(x)
309 } else {
310 Err(())
311 }
312 }
313}
314
315impl From<ecdsa::Signature> for MultiSignature {
316 fn from(x: ecdsa::Signature) -> Self {
317 Self::Ecdsa(x)
318 }
319}
320
321impl TryFrom<MultiSignature> for ecdsa::Signature {
322 type Error = ();
323 fn try_from(m: MultiSignature) -> Result<Self, Self::Error> {
324 if let MultiSignature::Ecdsa(x) = m {
325 Ok(x)
326 } else {
327 Err(())
328 }
329 }
330}
331
332#[derive(
334 Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo,
335)]
336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
337pub enum MultiSigner {
338 Ed25519(ed25519::Public),
340 Sr25519(sr25519::Public),
342 Ecdsa(ecdsa::Public),
344 Eth(ecdsa::KeccakPublic),
351}
352
353impl FromEntropy for MultiSigner {
354 fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
355 Ok(match input.read_byte()? % 4 {
356 0 => Self::Ed25519(FromEntropy::from_entropy(input)?),
357 1 => Self::Sr25519(FromEntropy::from_entropy(input)?),
358 2 => Self::Ecdsa(FromEntropy::from_entropy(input)?),
359 3.. => Self::Eth(FromEntropy::from_entropy(input)?),
360 })
361 }
362}
363
364impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
367 fn unchecked_from(x: T) -> Self {
368 ed25519::Public::unchecked_from(x.into()).into()
369 }
370}
371
372impl AsRef<[u8]> for MultiSigner {
373 fn as_ref(&self) -> &[u8] {
374 match *self {
375 Self::Ed25519(ref who) => who.as_ref(),
376 Self::Sr25519(ref who) => who.as_ref(),
377 Self::Ecdsa(ref who) => who.as_ref(),
378 Self::Eth(ref who) => who.as_ref(),
379 }
380 }
381}
382
383impl traits::IdentifyAccount for MultiSigner {
384 type AccountId = AccountId32;
385 fn into_account(self) -> AccountId32 {
386 match self {
387 Self::Ed25519(who) => <[u8; 32]>::from(who).into(),
388 Self::Sr25519(who) => <[u8; 32]>::from(who).into(),
389 Self::Ecdsa(who) => sp_io::hashing::blake2_256(who.as_ref()).into(),
390 Self::Eth(who) => {
391 let eth_address = &sp_io::hashing::keccak_256(who.as_ref())[12..];
395 let mut address = [0xEE; 32];
398 address[..20].copy_from_slice(eth_address);
399 address.into()
400 },
401 }
402 }
403}
404
405impl From<ed25519::Public> for MultiSigner {
406 fn from(x: ed25519::Public) -> Self {
407 Self::Ed25519(x)
408 }
409}
410
411impl TryFrom<MultiSigner> for ed25519::Public {
412 type Error = ();
413 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
414 if let MultiSigner::Ed25519(x) = m {
415 Ok(x)
416 } else {
417 Err(())
418 }
419 }
420}
421
422impl From<sr25519::Public> for MultiSigner {
423 fn from(x: sr25519::Public) -> Self {
424 Self::Sr25519(x)
425 }
426}
427
428impl TryFrom<MultiSigner> for sr25519::Public {
429 type Error = ();
430 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
431 if let MultiSigner::Sr25519(x) = m {
432 Ok(x)
433 } else {
434 Err(())
435 }
436 }
437}
438
439impl From<ecdsa::Public> for MultiSigner {
440 fn from(x: ecdsa::Public) -> Self {
441 Self::Ecdsa(x)
442 }
443}
444
445impl TryFrom<MultiSigner> for ecdsa::Public {
446 type Error = ();
447 fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
448 if let MultiSigner::Ecdsa(x) = m {
449 Ok(x)
450 } else {
451 Err(())
452 }
453 }
454}
455
456#[cfg(feature = "std")]
457impl std::fmt::Display for MultiSigner {
458 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
459 match self {
460 Self::Ed25519(who) => write!(fmt, "ed25519: {}", who),
461 Self::Sr25519(who) => write!(fmt, "sr25519: {}", who),
462 Self::Ecdsa(who) => write!(fmt, "ecdsa: {}", who),
463 Self::Eth(who) => write!(fmt, "eth: {}", who),
464 }
465 }
466}
467
468impl Verify for MultiSignature {
469 type Signer = MultiSigner;
470 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
471 let who: [u8; 32] = *signer.as_ref();
472 match self {
473 Self::Ed25519(sig) => sig.verify(msg, &who.into()),
474 Self::Sr25519(sig) => sig.verify(msg, &who.into()),
475 Self::Ecdsa(sig) => {
476 let sig_ref: &[u8; 65] = sig.as_ref();
477 if !ecdsa::is_signature_normalized(sig_ref) {
479 return false;
480 }
481 let m = sp_io::hashing::blake2_256(msg.get());
482 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig_ref, &m)
483 .map_or(false, |pubkey| sp_io::hashing::blake2_256(&pubkey) == who)
484 },
485 Self::Eth(sig) => {
486 let sig_ref: &[u8; 65] = sig.as_ref();
487 if !ecdsa::is_signature_normalized(sig_ref) {
489 return false;
490 }
491 let m = sp_io::hashing::keccak_256(msg.get());
492 sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig_ref, &m)
493 .map_or(false, |pubkey| {
494 &MultiSigner::Eth(pubkey.into()).into_account() == signer
495 })
496 },
497 }
498 }
499}
500
501#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, Debug, TypeInfo)]
503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
504pub struct AnySignature(H512);
505
506impl Verify for AnySignature {
507 type Signer = sr25519::Public;
508 fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
509 let msg = msg.get();
510 sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
511 .map(|s| s.verify(msg, signer))
512 .unwrap_or(false) ||
513 ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
514 .map(|s| match ed25519::Public::from_slice(signer.as_ref()) {
515 Err(()) => false,
516 Ok(signer) => s.verify(msg, &signer),
517 })
518 .unwrap_or(false)
519 }
520}
521
522impl From<sr25519::Signature> for AnySignature {
523 fn from(s: sr25519::Signature) -> Self {
524 Self(s.into())
525 }
526}
527
528impl From<ed25519::Signature> for AnySignature {
529 fn from(s: ed25519::Signature) -> Self {
530 Self(s.into())
531 }
532}
533
534impl From<DispatchError> for DispatchOutcome {
535 fn from(err: DispatchError) -> Self {
536 Err(err)
537 }
538}
539
540pub type DispatchResult = core::result::Result<(), DispatchError>;
544
545pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
548
549#[derive(
551 Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
552)]
553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
554pub struct ModuleError {
555 pub index: u8,
557 pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
559 #[codec(skip)]
561 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
562 pub message: Option<&'static str>,
563}
564
565impl PartialEq for ModuleError {
566 fn eq(&self, other: &Self) -> bool {
567 (self.index == other.index) && (self.error == other.error)
568 }
569}
570
571#[derive(
573 Eq,
574 PartialEq,
575 Clone,
576 Copy,
577 Encode,
578 Decode,
579 DecodeWithMemTracking,
580 Debug,
581 TypeInfo,
582 MaxEncodedLen,
583)]
584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
585pub enum TransactionalError {
586 LimitReached,
588 NoLayer,
590}
591
592impl From<TransactionalError> for &'static str {
593 fn from(e: TransactionalError) -> &'static str {
594 match e {
595 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
596 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
597 }
598 }
599}
600
601impl From<TransactionalError> for DispatchError {
602 fn from(e: TransactionalError) -> DispatchError {
603 Self::Transactional(e)
604 }
605}
606
607#[derive(
609 Eq,
610 Clone,
611 Copy,
612 Encode,
613 Decode,
614 DecodeWithMemTracking,
615 Debug,
616 TypeInfo,
617 PartialEq,
618 MaxEncodedLen,
619)]
620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
621pub enum DispatchError {
622 Other(
624 #[codec(skip)]
625 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
626 &'static str,
627 ),
628 CannotLookup,
630 BadOrigin,
632 Module(ModuleError),
634 ConsumerRemaining,
636 NoProviders,
638 TooManyConsumers,
640 Token(TokenError),
642 Arithmetic(ArithmeticError),
644 Transactional(TransactionalError),
647 Exhausted,
649 Corruption,
651 Unavailable,
653 RootNotAllowed,
655 Trie(TrieError),
657}
658
659#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
662pub struct DispatchErrorWithPostInfo<Info>
663where
664 Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
665{
666 pub post_info: Info,
668 pub error: DispatchError,
670}
671
672impl DispatchError {
673 pub fn stripped(self) -> Self {
675 match self {
676 DispatchError::Module(ModuleError { index, error, message: Some(_) }) => {
677 DispatchError::Module(ModuleError { index, error, message: None })
678 },
679 m => m,
680 }
681 }
682}
683
684impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
685where
686 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
687 E: Into<DispatchError>,
688{
689 fn from(error: E) -> Self {
690 Self { post_info: Default::default(), error: error.into() }
691 }
692}
693
694impl From<crate::traits::LookupError> for DispatchError {
695 fn from(_: crate::traits::LookupError) -> Self {
696 Self::CannotLookup
697 }
698}
699
700impl From<crate::traits::BadOrigin> for DispatchError {
701 fn from(_: crate::traits::BadOrigin) -> Self {
702 Self::BadOrigin
703 }
704}
705
706#[derive(
708 Eq,
709 PartialEq,
710 Clone,
711 Copy,
712 Encode,
713 Decode,
714 DecodeWithMemTracking,
715 Debug,
716 TypeInfo,
717 MaxEncodedLen,
718)]
719#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
720pub enum TokenError {
721 FundsUnavailable,
723 OnlyProvider,
726 BelowMinimum,
728 CannotCreate,
730 UnknownAsset,
732 Frozen,
734 Unsupported,
736 CannotCreateHold,
738 NotExpendable,
740 Blocked,
742}
743
744impl From<TokenError> for &'static str {
745 fn from(e: TokenError) -> &'static str {
746 match e {
747 TokenError::FundsUnavailable => "Funds are unavailable",
748 TokenError::OnlyProvider => "Account that must exist would die",
749 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
750 TokenError::CannotCreate => "Account cannot be created",
751 TokenError::UnknownAsset => "The asset in question is unknown",
752 TokenError::Frozen => "Funds exist but are frozen",
753 TokenError::Unsupported => "Operation is not supported by the asset",
754 TokenError::CannotCreateHold => {
755 "Account cannot be created for recording amount on hold"
756 },
757 TokenError::NotExpendable => "Account that is desired to remain would die",
758 TokenError::Blocked => "Account cannot receive the assets",
759 }
760 }
761}
762
763impl From<TokenError> for DispatchError {
764 fn from(e: TokenError) -> DispatchError {
765 Self::Token(e)
766 }
767}
768
769impl From<ArithmeticError> for DispatchError {
770 fn from(e: ArithmeticError) -> DispatchError {
771 Self::Arithmetic(e)
772 }
773}
774
775impl From<TrieError> for DispatchError {
776 fn from(e: TrieError) -> DispatchError {
777 Self::Trie(e)
778 }
779}
780
781impl From<&'static str> for DispatchError {
782 fn from(err: &'static str) -> DispatchError {
783 Self::Other(err)
784 }
785}
786
787impl From<DispatchError> for &'static str {
788 fn from(err: DispatchError) -> &'static str {
789 use DispatchError::*;
790 match err {
791 Other(msg) => msg,
792 CannotLookup => "Cannot lookup",
793 BadOrigin => "Bad origin",
794 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
795 ConsumerRemaining => "Consumer remaining",
796 NoProviders => "No providers",
797 TooManyConsumers => "Too many consumers",
798 Token(e) => e.into(),
799 Arithmetic(e) => e.into(),
800 Transactional(e) => e.into(),
801 Exhausted => "Resources exhausted",
802 Corruption => "State corrupt",
803 Unavailable => "Resource unavailable",
804 RootNotAllowed => "Root not allowed",
805 Trie(e) => e.into(),
806 }
807 }
808}
809
810impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
811where
812 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
813{
814 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
815 err.error.into()
816 }
817}
818
819impl traits::Printable for DispatchError {
820 fn print(&self) {
821 use DispatchError::*;
822 "DispatchError".print();
823 match self {
824 Other(err) => err.print(),
825 CannotLookup => "Cannot lookup".print(),
826 BadOrigin => "Bad origin".print(),
827 Module(ModuleError { index, error, message }) => {
828 index.print();
829 error.print();
830 if let Some(msg) = message {
831 msg.print();
832 }
833 },
834 ConsumerRemaining => "Consumer remaining".print(),
835 NoProviders => "No providers".print(),
836 TooManyConsumers => "Too many consumers".print(),
837 Token(e) => {
838 "Token error: ".print();
839 <&'static str>::from(*e).print();
840 },
841 Arithmetic(e) => {
842 "Arithmetic error: ".print();
843 <&'static str>::from(*e).print();
844 },
845 Transactional(e) => {
846 "Transactional error: ".print();
847 <&'static str>::from(*e).print();
848 },
849 Exhausted => "Resources exhausted".print(),
850 Corruption => "State corrupt".print(),
851 Unavailable => "Resource unavailable".print(),
852 RootNotAllowed => "Root not allowed".print(),
853 Trie(e) => {
854 "Trie error: ".print();
855 <&'static str>::from(*e).print();
856 },
857 }
858 }
859}
860
861impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
862where
863 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
864{
865 fn print(&self) {
866 self.error.print();
867 "PostInfo: ".print();
868 self.post_info.print();
869 }
870}
871
872pub type DispatchOutcome = Result<(), DispatchError>;
882
883pub type ApplyExtrinsicResult =
902 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
903
904pub type ApplyExtrinsicResultWithInfo<T> =
906 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
907
908pub type TryRuntimeError = DispatchError;
910
911pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
914 sig: &V,
915 item: &T,
916 signer: &<V::Signer as IdentifyAccount>::AccountId,
917) -> bool {
918 struct LazyEncode<F> {
923 inner: F,
924 encoded: Option<Vec<u8>>,
925 }
926
927 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
928 fn get(&mut self) -> &[u8] {
929 self.encoded.get_or_insert_with(&self.inner).as_slice()
930 }
931 }
932
933 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
934}
935
936#[macro_export]
954#[cfg(feature = "std")]
955macro_rules! assert_eq_error_rate {
956 ($x:expr, $y:expr, $error:expr $(,)?) => {
957 assert!(
958 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
959 ($x <= $crate::Saturating::saturating_add($y, $error)),
960 "{:?} != {:?} (with error rate {:?})",
961 $x,
962 $y,
963 $error,
964 );
965 };
966}
967
968#[macro_export]
971#[cfg(feature = "std")]
972macro_rules! assert_eq_error_rate_float {
973 ($x:expr, $y:expr, $error:expr $(,)?) => {
974 assert!(
975 ($x >= $y - $error) && ($x <= $y + $error),
976 "{:?} != {:?} (with error rate {:?})",
977 $x,
978 $y,
979 $error,
980 );
981 };
982}
983
984#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
987pub struct OpaqueExtrinsic(bytes::Bytes);
988
989impl TypeInfo for OpaqueExtrinsic {
990 type Identity = Self;
991 fn type_info() -> scale_info::Type {
992 scale_info::Type::builder()
993 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
994 .composite(
995 scale_info::build::Fields::unnamed()
996 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
997 )
998 }
999}
1000
1001impl OpaqueExtrinsic {
1002 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1004 Self::decode(&mut bytes)
1005 }
1006
1007 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
1009 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
1010 Self::try_from_encoded_extrinsic(bytes)
1011 }
1012
1013 pub fn from_blob(bytes: Vec<u8>) -> Self {
1015 Self(bytes.into())
1016 }
1017
1018 pub fn inner(&self) -> &[u8] {
1020 &self.0
1021 }
1022}
1023
1024impl LazyExtrinsic for OpaqueExtrinsic {
1025 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
1026 Ok(Self(data.to_vec().into()))
1027 }
1028}
1029
1030impl core::fmt::Debug for OpaqueExtrinsic {
1031 #[cfg(feature = "std")]
1032 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1033 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1034 }
1035
1036 #[cfg(not(feature = "std"))]
1037 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1038 Ok(())
1039 }
1040}
1041
1042#[cfg(feature = "serde")]
1043impl ::serde::Serialize for OpaqueExtrinsic {
1044 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1045 where
1046 S: ::serde::Serializer,
1047 {
1048 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1049 }
1050}
1051
1052#[cfg(feature = "serde")]
1053impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1054 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1055 where
1056 D: ::serde::Deserializer<'a>,
1057 {
1058 let r = ::sp_core::bytes::deserialize(de)?;
1059 Decode::decode(&mut &r[..])
1060 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1061 }
1062}
1063
1064impl traits::ExtrinsicLike for OpaqueExtrinsic {
1065 fn is_bare(&self) -> bool {
1066 false
1067 }
1068}
1069
1070pub fn print(print: impl traits::Printable) {
1072 print.print();
1073}
1074
1075pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1090 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1091 let mut i = 0;
1092 let mut arr = [0; N];
1093 let s = s.as_bytes();
1094 while i < s.len() {
1095 arr[i] = s[i];
1096 i += 1;
1097 }
1098 arr
1099}
1100
1101pub enum TransactionOutcome<R> {
1103 Commit(R),
1105 Rollback(R),
1107}
1108
1109impl<R> TransactionOutcome<R> {
1110 pub fn into_inner(self) -> R {
1112 match self {
1113 Self::Commit(r) => r,
1114 Self::Rollback(r) => r,
1115 }
1116 }
1117}
1118
1119#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1121pub enum ExtrinsicInclusionMode {
1122 #[default]
1124 AllExtrinsics,
1125 OnlyInherents,
1127}
1128
1129#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
1131pub struct OpaqueValue(Vec<u8>);
1132impl OpaqueValue {
1133 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1135 OpaqueValue(inner)
1136 }
1137
1138 pub fn decode<T: Decode>(&self) -> Option<T> {
1140 Decode::decode(&mut &self.0[..]).ok()
1141 }
1142}
1143
1144#[macro_export]
1147#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1148macro_rules! create_runtime_str {
1149 ( $y:expr ) => {{
1150 $crate::Cow::Borrowed($y)
1151 }};
1152}
1153#[doc(hidden)]
1155pub use alloc::borrow::Cow;
1156
1157#[deprecated = "Use String or Cow<'static, str> instead"]
1160pub type RuntimeString = alloc::string::String;
1161
1162#[cfg(test)]
1163mod tests {
1164 use crate::traits::BlakeTwo256;
1165
1166 use super::*;
1167 use codec::{Decode, Encode};
1168 use sp_core::{crypto::Pair, hex2array};
1169 use sp_io::TestExternalities;
1170 use sp_state_machine::create_proof_check_backend;
1171
1172 #[test]
1173 fn opaque_extrinsic_serialization() {
1174 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1175 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1176 }
1177
1178 #[test]
1179 fn dispatch_error_encoding() {
1180 let error = DispatchError::Module(ModuleError {
1181 index: 1,
1182 error: [2, 0, 0, 0],
1183 message: Some("error message"),
1184 });
1185 let encoded = error.encode();
1186 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1187 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1188 assert_eq!(
1189 decoded,
1190 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1191 );
1192 }
1193
1194 #[test]
1195 fn dispatch_error_equality() {
1196 use DispatchError::*;
1197
1198 let variants = vec![
1199 Other("foo"),
1200 Other("bar"),
1201 CannotLookup,
1202 BadOrigin,
1203 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1204 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1205 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1206 ConsumerRemaining,
1207 NoProviders,
1208 Token(TokenError::FundsUnavailable),
1209 Token(TokenError::OnlyProvider),
1210 Token(TokenError::BelowMinimum),
1211 Token(TokenError::CannotCreate),
1212 Token(TokenError::UnknownAsset),
1213 Token(TokenError::Frozen),
1214 Arithmetic(ArithmeticError::Overflow),
1215 Arithmetic(ArithmeticError::Underflow),
1216 Arithmetic(ArithmeticError::DivisionByZero),
1217 ];
1218 for (i, variant) in variants.iter().enumerate() {
1219 for (j, other_variant) in variants.iter().enumerate() {
1220 if i == j {
1221 assert_eq!(variant, other_variant);
1222 } else {
1223 assert_ne!(variant, other_variant);
1224 }
1225 }
1226 }
1227
1228 assert_eq!(
1230 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1231 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1232 );
1233 }
1234
1235 #[test]
1236 fn multi_signature_ecdsa_verify_works() {
1237 let msg = &b"test-message"[..];
1238 let (pair, _) = ecdsa::Pair::generate();
1239
1240 let signature = pair.sign(&msg);
1241 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1242
1243 let multi_sig = MultiSignature::from(signature);
1244 let multi_signer = MultiSigner::from(pair.public());
1245 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1246 }
1247
1248 #[test]
1249 fn multi_signature_eth_verify_works() {
1250 let msg = &b"test-message"[..];
1251 let (pair, _) = ecdsa::KeccakPair::generate();
1252
1253 let signature = pair.sign(&msg);
1254 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1255
1256 let multi_sig = MultiSignature::Eth(signature);
1257 let multi_signer = MultiSigner::Eth(pair.public());
1258 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1259 }
1260
1261 pub(crate) fn make_high_s_signature(sig: &[u8; 65]) -> [u8; 65] {
1264 let order: [u8; 32] = [
1266 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1267 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
1268 0xd0, 0x36, 0x41, 0x41,
1269 ];
1270 let s_bytes: [u8; 32] = sig[32..64].try_into().unwrap();
1271 let mut s_prime = [0u8; 32];
1272 let mut borrow = 0i16;
1273 for i in (0..32).rev() {
1274 let diff = order[i] as i16 - s_bytes[i] as i16 - borrow;
1275 if diff < 0 {
1276 s_prime[i] = (diff + 256) as u8;
1277 borrow = 1;
1278 } else {
1279 s_prime[i] = diff as u8;
1280 borrow = 0;
1281 }
1282 }
1283 let mut out = [0u8; 65];
1284 out[0..32].copy_from_slice(&sig[0..32]);
1285 out[32..64].copy_from_slice(&s_prime);
1286 out[64] = sig[64] ^ 1;
1287 out
1288 }
1289
1290 #[test]
1291 fn multi_signature_ecdsa_rejects_high_s() {
1292 let msg = &b"test-message"[..];
1293 let (pair, _) = ecdsa::Pair::generate();
1294
1295 let signature = pair.sign(&msg);
1296 let multi_signer = MultiSigner::from(pair.public());
1297 let account = multi_signer.into_account();
1298
1299 let multi_sig = MultiSignature::from(signature);
1301 assert!(multi_sig.verify(msg, &account));
1302
1303 let sig_bytes: &[u8; 65] = signature.as_ref();
1305 let malleable = make_high_s_signature(sig_bytes);
1306 let malleable_sig = MultiSignature::Ecdsa(ecdsa::Signature::from_raw(malleable));
1307 assert!(
1308 !malleable_sig.verify(msg, &account),
1309 "high-S ECDSA signature should be rejected by MultiSignature"
1310 );
1311 }
1312
1313 #[test]
1314 fn multi_signature_eth_rejects_high_s() {
1315 let msg = &b"test-message"[..];
1316 let (pair, _) = ecdsa::KeccakPair::generate();
1317
1318 let signature = pair.sign(&msg);
1319 let multi_signer = MultiSigner::Eth(pair.public());
1320 let account = multi_signer.into_account();
1321
1322 let multi_sig = MultiSignature::Eth(signature);
1324 assert!(multi_sig.verify(msg, &account));
1325
1326 let sig_bytes: &[u8; 65] = signature.as_ref();
1328 let malleable = make_high_s_signature(sig_bytes);
1329 let malleable_sig = MultiSignature::Eth(ecdsa::KeccakSignature::from_raw(malleable));
1330 assert!(
1331 !malleable_sig.verify(msg, &account),
1332 "high-S Eth signature should be rejected by MultiSignature"
1333 );
1334 }
1335
1336 #[test]
1337 fn multi_signer_eth_address_works() {
1338 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1339 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1340 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1341 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1342
1343 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1344 assert_eq!(
1345 ecdsa,
1346 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1347 );
1348 assert_eq!(
1349 eth,
1350 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1351 );
1352 }
1353
1354 #[test]
1355 fn execute_and_generate_proof_works() {
1356 use codec::Encode;
1357 use sp_state_machine::Backend;
1358 let mut ext = TestExternalities::default();
1359
1360 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1361 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1362 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1363 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1364
1365 let pre_root = *ext.backend.root();
1366 let (_, proof) = ext.execute_and_prove(|| {
1367 sp_io::storage::get(b"a");
1368 sp_io::storage::get(b"b");
1369 sp_io::storage::get(b"v");
1370 sp_io::storage::get(b"d");
1371 });
1372
1373 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1374 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1375
1376 println!("proof size: {:?}", proof.encoded_size());
1378 println!("compact proof size: {:?}", compact_proof.encoded_size());
1379 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1380
1381 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1383 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1384
1385 let _ = ext.execute_and_prove(|| {
1386 sp_io::storage::set(b"a", &vec![1u8; 44]);
1387 });
1388
1389 ext.execute_with(|| {
1392 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1393 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1394 });
1395 }
1396}
1397
1398#[cfg(test)]
1401mod sp_core_tests {
1402 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1403 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1404
1405 #[test]
1406 #[should_panic]
1407 fn generate_feature_enabled_macro_panics() {
1408 if_test!(panic!("This should panic"));
1409 }
1410
1411 #[test]
1412 fn generate_feature_enabled_macro_works() {
1413 if_not_test!(panic!("This should not panic"));
1414 }
1415}