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(
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 struct ModuleInvalidity {
589 pub index: u8,
591 pub error: u16,
593}
594
595#[derive(
597 Eq,
598 PartialEq,
599 Clone,
600 Copy,
601 Encode,
602 Decode,
603 DecodeWithMemTracking,
604 Debug,
605 TypeInfo,
606 MaxEncodedLen,
607)]
608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
609pub enum TransactionalError {
610 LimitReached,
612 NoLayer,
614}
615
616impl From<TransactionalError> for &'static str {
617 fn from(e: TransactionalError) -> &'static str {
618 match e {
619 TransactionalError::LimitReached => "Too many transactional layers have been spawned",
620 TransactionalError::NoLayer => "A transactional layer was expected, but does not exist",
621 }
622 }
623}
624
625impl From<TransactionalError> for DispatchError {
626 fn from(e: TransactionalError) -> DispatchError {
627 Self::Transactional(e)
628 }
629}
630
631#[derive(
633 Eq,
634 Clone,
635 Copy,
636 Encode,
637 Decode,
638 DecodeWithMemTracking,
639 Debug,
640 TypeInfo,
641 PartialEq,
642 MaxEncodedLen,
643)]
644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
645pub enum DispatchError {
646 Other(
648 #[codec(skip)]
649 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
650 &'static str,
651 ),
652 CannotLookup,
654 BadOrigin,
656 Module(ModuleError),
658 ConsumerRemaining,
660 NoProviders,
662 TooManyConsumers,
664 Token(TokenError),
666 Arithmetic(ArithmeticError),
668 Transactional(TransactionalError),
671 Exhausted,
673 Corruption,
675 Unavailable,
677 RootNotAllowed,
679 Trie(TrieError),
681}
682
683#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
686pub struct DispatchErrorWithPostInfo<Info>
687where
688 Info: Eq + PartialEq + Clone + Copy + Encode + Decode,
689{
690 pub post_info: Info,
692 pub error: DispatchError,
694}
695
696impl DispatchError {
697 pub fn stripped(self) -> Self {
699 match self {
700 DispatchError::Module(ModuleError { index, error, message: Some(_) }) => {
701 DispatchError::Module(ModuleError { index, error, message: None })
702 },
703 m => m,
704 }
705 }
706}
707
708impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
709where
710 T: Eq + PartialEq + Clone + Copy + Encode + Decode + Default,
711 E: Into<DispatchError>,
712{
713 fn from(error: E) -> Self {
714 Self { post_info: Default::default(), error: error.into() }
715 }
716}
717
718impl From<crate::traits::LookupError> for DispatchError {
719 fn from(_: crate::traits::LookupError) -> Self {
720 Self::CannotLookup
721 }
722}
723
724impl From<crate::traits::BadOrigin> for DispatchError {
725 fn from(_: crate::traits::BadOrigin) -> Self {
726 Self::BadOrigin
727 }
728}
729
730#[derive(
732 Eq,
733 PartialEq,
734 Clone,
735 Copy,
736 Encode,
737 Decode,
738 DecodeWithMemTracking,
739 Debug,
740 TypeInfo,
741 MaxEncodedLen,
742)]
743#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
744pub enum TokenError {
745 FundsUnavailable,
747 OnlyProvider,
750 BelowMinimum,
752 CannotCreate,
754 UnknownAsset,
756 Frozen,
758 Unsupported,
760 CannotCreateHold,
762 NotExpendable,
764 Blocked,
766}
767
768impl From<TokenError> for &'static str {
769 fn from(e: TokenError) -> &'static str {
770 match e {
771 TokenError::FundsUnavailable => "Funds are unavailable",
772 TokenError::OnlyProvider => "Account that must exist would die",
773 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
774 TokenError::CannotCreate => "Account cannot be created",
775 TokenError::UnknownAsset => "The asset in question is unknown",
776 TokenError::Frozen => "Funds exist but are frozen",
777 TokenError::Unsupported => "Operation is not supported by the asset",
778 TokenError::CannotCreateHold => {
779 "Account cannot be created for recording amount on hold"
780 },
781 TokenError::NotExpendable => "Account that is desired to remain would die",
782 TokenError::Blocked => "Account cannot receive the assets",
783 }
784 }
785}
786
787impl From<TokenError> for DispatchError {
788 fn from(e: TokenError) -> DispatchError {
789 Self::Token(e)
790 }
791}
792
793impl From<ArithmeticError> for DispatchError {
794 fn from(e: ArithmeticError) -> DispatchError {
795 Self::Arithmetic(e)
796 }
797}
798
799impl From<TrieError> for DispatchError {
800 fn from(e: TrieError) -> DispatchError {
801 Self::Trie(e)
802 }
803}
804
805impl From<&'static str> for DispatchError {
806 fn from(err: &'static str) -> DispatchError {
807 Self::Other(err)
808 }
809}
810
811impl From<DispatchError> for &'static str {
812 fn from(err: DispatchError) -> &'static str {
813 use DispatchError::*;
814 match err {
815 Other(msg) => msg,
816 CannotLookup => "Cannot lookup",
817 BadOrigin => "Bad origin",
818 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
819 ConsumerRemaining => "Consumer remaining",
820 NoProviders => "No providers",
821 TooManyConsumers => "Too many consumers",
822 Token(e) => e.into(),
823 Arithmetic(e) => e.into(),
824 Transactional(e) => e.into(),
825 Exhausted => "Resources exhausted",
826 Corruption => "State corrupt",
827 Unavailable => "Resource unavailable",
828 RootNotAllowed => "Root not allowed",
829 Trie(e) => e.into(),
830 }
831 }
832}
833
834impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
835where
836 T: Eq + PartialEq + Clone + Copy + Encode + Decode,
837{
838 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
839 err.error.into()
840 }
841}
842
843pub type DispatchOutcome = Result<(), DispatchError>;
853
854pub type ApplyExtrinsicResult =
873 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
874
875pub type ApplyExtrinsicResultWithInfo<T> =
877 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
878
879pub type TryRuntimeError = DispatchError;
881
882pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
885 sig: &V,
886 item: &T,
887 signer: &<V::Signer as IdentifyAccount>::AccountId,
888) -> bool {
889 struct LazyEncode<F> {
894 inner: F,
895 encoded: Option<Vec<u8>>,
896 }
897
898 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
899 fn get(&mut self) -> &[u8] {
900 self.encoded.get_or_insert_with(&self.inner).as_slice()
901 }
902 }
903
904 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
905}
906
907#[macro_export]
925#[cfg(feature = "std")]
926macro_rules! assert_eq_error_rate {
927 ($x:expr, $y:expr, $error:expr $(,)?) => {
928 assert!(
929 ($x >= $crate::Saturating::saturating_sub($y, $error)) &&
930 ($x <= $crate::Saturating::saturating_add($y, $error)),
931 "{:?} != {:?} (with error rate {:?})",
932 $x,
933 $y,
934 $error,
935 );
936 };
937}
938
939#[macro_export]
942#[cfg(feature = "std")]
943macro_rules! assert_eq_error_rate_float {
944 ($x:expr, $y:expr, $error:expr $(,)?) => {
945 assert!(
946 ($x >= $y - $error) && ($x <= $y + $error),
947 "{:?} != {:?} (with error rate {:?})",
948 $x,
949 $y,
950 $error,
951 );
952 };
953}
954
955#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
958pub struct OpaqueExtrinsic(bytes::Bytes);
959
960impl TypeInfo for OpaqueExtrinsic {
961 type Identity = Self;
962 fn type_info() -> scale_info::Type {
963 scale_info::Type::builder()
964 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
965 .composite(
966 scale_info::build::Fields::unnamed()
967 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
968 )
969 }
970}
971
972impl OpaqueExtrinsic {
973 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
975 Self::decode(&mut bytes)
976 }
977
978 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
980 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
981 Self::try_from_encoded_extrinsic(bytes)
982 }
983
984 pub fn from_blob(bytes: Vec<u8>) -> Self {
986 Self(bytes.into())
987 }
988
989 pub fn inner(&self) -> &[u8] {
991 &self.0
992 }
993}
994
995impl LazyExtrinsic for OpaqueExtrinsic {
996 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
997 Ok(Self(data.to_vec().into()))
998 }
999}
1000
1001impl core::fmt::Debug for OpaqueExtrinsic {
1002 #[cfg(feature = "std")]
1003 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1004 write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1005 }
1006
1007 #[cfg(not(feature = "std"))]
1008 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1009 Ok(())
1010 }
1011}
1012
1013#[cfg(feature = "serde")]
1014impl ::serde::Serialize for OpaqueExtrinsic {
1015 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1016 where
1017 S: ::serde::Serializer,
1018 {
1019 codec::Encode::using_encoded(&self.0, |bytes| ::sp_core::bytes::serialize(bytes, seq))
1020 }
1021}
1022
1023#[cfg(feature = "serde")]
1024impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1025 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1026 where
1027 D: ::serde::Deserializer<'a>,
1028 {
1029 let r = ::sp_core::bytes::deserialize(de)?;
1030 Decode::decode(&mut &r[..])
1031 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1032 }
1033}
1034
1035impl traits::ExtrinsicLike for OpaqueExtrinsic {
1036 fn is_bare(&self) -> bool {
1037 false
1038 }
1039}
1040
1041pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1056 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1057 let mut i = 0;
1058 let mut arr = [0; N];
1059 let s = s.as_bytes();
1060 while i < s.len() {
1061 arr[i] = s[i];
1062 i += 1;
1063 }
1064 arr
1065}
1066
1067pub enum TransactionOutcome<R> {
1069 Commit(R),
1071 Rollback(R),
1073}
1074
1075impl<R> TransactionOutcome<R> {
1076 pub fn into_inner(self) -> R {
1078 match self {
1079 Self::Commit(r) => r,
1080 Self::Rollback(r) => r,
1081 }
1082 }
1083}
1084
1085#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1087pub enum ExtrinsicInclusionMode {
1088 #[default]
1090 AllExtrinsics,
1091 OnlyInherents,
1093}
1094
1095#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
1097pub struct OpaqueValue(Vec<u8>);
1098impl OpaqueValue {
1099 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1101 OpaqueValue(inner)
1102 }
1103
1104 pub fn decode<T: Decode>(&self) -> Option<T> {
1106 Decode::decode(&mut &self.0[..]).ok()
1107 }
1108}
1109
1110#[macro_export]
1113#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1114macro_rules! create_runtime_str {
1115 ( $y:expr ) => {{
1116 $crate::Cow::Borrowed($y)
1117 }};
1118}
1119#[doc(hidden)]
1121pub use alloc::borrow::Cow;
1122
1123#[deprecated = "Use String or Cow<'static, str> instead"]
1126pub type RuntimeString = alloc::string::String;
1127
1128#[cfg(test)]
1129mod tests {
1130 use crate::traits::BlakeTwo256;
1131
1132 use super::*;
1133 use codec::{Decode, Encode};
1134 use sp_core::{crypto::Pair, hex2array};
1135 use sp_io::TestExternalities;
1136 use sp_state_machine::create_proof_check_backend;
1137
1138 #[test]
1139 fn opaque_extrinsic_serialization() {
1140 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1141 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1142 }
1143
1144 #[test]
1145 fn dispatch_error_encoding() {
1146 let error = DispatchError::Module(ModuleError {
1147 index: 1,
1148 error: [2, 0, 0, 0],
1149 message: Some("error message"),
1150 });
1151 let encoded = error.encode();
1152 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1153 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1154 assert_eq!(
1155 decoded,
1156 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1157 );
1158 }
1159
1160 #[test]
1161 fn module_invalidity_should_encode_and_decode() {
1162 let invalidity = ModuleInvalidity { index: 7, error: 3 };
1163 let encoded = invalidity.encode();
1164 let decoded = ModuleInvalidity::decode(&mut &encoded[..]).unwrap();
1165 assert_eq!(encoded, vec![7, 3, 0]);
1166 assert_eq!(decoded, invalidity);
1167 }
1168
1169 #[test]
1170 fn dispatch_error_equality() {
1171 use DispatchError::*;
1172
1173 let variants = vec![
1174 Other("foo"),
1175 Other("bar"),
1176 CannotLookup,
1177 BadOrigin,
1178 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1179 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1180 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1181 ConsumerRemaining,
1182 NoProviders,
1183 Token(TokenError::FundsUnavailable),
1184 Token(TokenError::OnlyProvider),
1185 Token(TokenError::BelowMinimum),
1186 Token(TokenError::CannotCreate),
1187 Token(TokenError::UnknownAsset),
1188 Token(TokenError::Frozen),
1189 Arithmetic(ArithmeticError::Overflow),
1190 Arithmetic(ArithmeticError::Underflow),
1191 Arithmetic(ArithmeticError::DivisionByZero),
1192 ];
1193 for (i, variant) in variants.iter().enumerate() {
1194 for (j, other_variant) in variants.iter().enumerate() {
1195 if i == j {
1196 assert_eq!(variant, other_variant);
1197 } else {
1198 assert_ne!(variant, other_variant);
1199 }
1200 }
1201 }
1202
1203 assert_eq!(
1205 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1206 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1207 );
1208 }
1209
1210 #[test]
1211 fn multi_signature_ecdsa_verify_works() {
1212 let msg = &b"test-message"[..];
1213 let (pair, _) = ecdsa::Pair::generate();
1214
1215 let signature = pair.sign(&msg);
1216 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1217
1218 let multi_sig = MultiSignature::from(signature);
1219 let multi_signer = MultiSigner::from(pair.public());
1220 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1221 }
1222
1223 #[test]
1224 fn multi_signature_eth_verify_works() {
1225 let msg = &b"test-message"[..];
1226 let (pair, _) = ecdsa::KeccakPair::generate();
1227
1228 let signature = pair.sign(&msg);
1229 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1230
1231 let multi_sig = MultiSignature::Eth(signature);
1232 let multi_signer = MultiSigner::Eth(pair.public());
1233 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1234 }
1235
1236 pub(crate) fn make_high_s_signature(sig: &[u8; 65]) -> [u8; 65] {
1239 let order: [u8; 32] = [
1241 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1242 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
1243 0xd0, 0x36, 0x41, 0x41,
1244 ];
1245 let s_bytes: [u8; 32] = sig[32..64].try_into().unwrap();
1246 let mut s_prime = [0u8; 32];
1247 let mut borrow = 0i16;
1248 for i in (0..32).rev() {
1249 let diff = order[i] as i16 - s_bytes[i] as i16 - borrow;
1250 if diff < 0 {
1251 s_prime[i] = (diff + 256) as u8;
1252 borrow = 1;
1253 } else {
1254 s_prime[i] = diff as u8;
1255 borrow = 0;
1256 }
1257 }
1258 let mut out = [0u8; 65];
1259 out[0..32].copy_from_slice(&sig[0..32]);
1260 out[32..64].copy_from_slice(&s_prime);
1261 out[64] = sig[64] ^ 1;
1262 out
1263 }
1264
1265 #[test]
1266 fn multi_signature_ecdsa_rejects_high_s() {
1267 let msg = &b"test-message"[..];
1268 let (pair, _) = ecdsa::Pair::generate();
1269
1270 let signature = pair.sign(&msg);
1271 let multi_signer = MultiSigner::from(pair.public());
1272 let account = multi_signer.into_account();
1273
1274 let multi_sig = MultiSignature::from(signature);
1276 assert!(multi_sig.verify(msg, &account));
1277
1278 let sig_bytes: &[u8; 65] = signature.as_ref();
1280 let malleable = make_high_s_signature(sig_bytes);
1281 let malleable_sig = MultiSignature::Ecdsa(ecdsa::Signature::from_raw(malleable));
1282 assert!(
1283 !malleable_sig.verify(msg, &account),
1284 "high-S ECDSA signature should be rejected by MultiSignature"
1285 );
1286 }
1287
1288 #[test]
1289 fn multi_signature_eth_rejects_high_s() {
1290 let msg = &b"test-message"[..];
1291 let (pair, _) = ecdsa::KeccakPair::generate();
1292
1293 let signature = pair.sign(&msg);
1294 let multi_signer = MultiSigner::Eth(pair.public());
1295 let account = multi_signer.into_account();
1296
1297 let multi_sig = MultiSignature::Eth(signature);
1299 assert!(multi_sig.verify(msg, &account));
1300
1301 let sig_bytes: &[u8; 65] = signature.as_ref();
1303 let malleable = make_high_s_signature(sig_bytes);
1304 let malleable_sig = MultiSignature::Eth(ecdsa::KeccakSignature::from_raw(malleable));
1305 assert!(
1306 !malleable_sig.verify(msg, &account),
1307 "high-S Eth signature should be rejected by MultiSignature"
1308 );
1309 }
1310
1311 #[test]
1312 fn multi_signer_eth_address_works() {
1313 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1314 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1315 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1316 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1317
1318 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1319 assert_eq!(
1320 ecdsa,
1321 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1322 );
1323 assert_eq!(
1324 eth,
1325 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1326 );
1327 }
1328
1329 #[test]
1330 fn execute_and_generate_proof_works() {
1331 use codec::Encode;
1332 use sp_state_machine::Backend;
1333 let mut ext = TestExternalities::default();
1334
1335 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1336 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1337 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1338 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1339
1340 let pre_root = *ext.backend.root();
1341 let (_, proof) = ext.execute_and_prove(|| {
1342 sp_io::storage::get(b"a");
1343 sp_io::storage::get(b"b");
1344 sp_io::storage::get(b"v");
1345 sp_io::storage::get(b"d");
1346 });
1347
1348 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1349 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1350
1351 println!("proof size: {:?}", proof.encoded_size());
1353 println!("compact proof size: {:?}", compact_proof.encoded_size());
1354 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1355
1356 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1358 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1359
1360 let _ = ext.execute_and_prove(|| {
1361 sp_io::storage::set(b"a", &vec![1u8; 44]);
1362 });
1363
1364 ext.execute_with(|| {
1367 assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1368 assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1369 });
1370 }
1371}
1372
1373#[cfg(test)]
1376mod sp_core_tests {
1377 sp_core::generate_feature_enabled_macro!(if_test, test, $);
1378 sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1379
1380 #[test]
1381 #[should_panic]
1382 fn generate_feature_enabled_macro_panics() {
1383 if_test!(panic!("This should panic"));
1384 }
1385
1386 #[test]
1387 fn generate_feature_enabled_macro_works() {
1388 if_not_test!(panic!("This should not panic"));
1389 }
1390}