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 pezsp_std;
57#[doc(hidden)]
58pub use scale_info;
59#[cfg(feature = "serde")]
60#[doc(hidden)]
61pub use serde;
62
63#[doc(hidden)]
64pub use paste;
65#[doc(hidden)]
66pub use pezsp_arithmetic::traits::Saturating;
67
68#[doc(hidden)]
69pub use pezsp_application_crypto as app_crypto;
70
71pub use pezsp_core::storage::StateVersion;
72#[cfg(feature = "std")]
73pub use pezsp_core::storage::{Storage, StorageChild};
74
75use pezsp_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 pezsp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
108pub use pezsp_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 pezsp_core::{bounded_btree_map, bounded_vec};
117
118pub use pezsp_core::RuntimeDebug;
120
121pub use pezsp_arithmetic::biguint;
123pub use pezsp_arithmetic::helpers_128bit;
125pub use pezsp_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 pezsp_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<pezsp_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 pezsp_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 pezsp_core::storage::Storage,
246 ) -> Result<(), String>;
247}
248
249#[cfg(feature = "std")]
250impl BuildStorage for pezsp_core::storage::Storage {
251 fn assimilate_storage(&self, storage: &mut pezsp_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 pezsp_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) => pezsp_io::hashing::blake2_256(who.as_ref()).into(),
420 Self::Eth(who) => {
421 let eth_address = &pezsp_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 = pezsp_io::hashing::blake2_256(msg.get());
507 pezsp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m)
508 .map_or(false, |pubkey| pezsp_io::hashing::blake2_256(&pubkey) == who)
509 },
510 Self::Eth(sig) => {
511 let m = pezsp_io::hashing::keccak_256(msg.get());
512 pezsp_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 },
699 m => m,
700 }
701 }
702}
703
704impl<T, E> From<E> for DispatchErrorWithPostInfo<T>
705where
706 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable + Default,
707 E: Into<DispatchError>,
708{
709 fn from(error: E) -> Self {
710 Self { post_info: Default::default(), error: error.into() }
711 }
712}
713
714impl From<crate::traits::LookupError> for DispatchError {
715 fn from(_: crate::traits::LookupError) -> Self {
716 Self::CannotLookup
717 }
718}
719
720impl From<crate::traits::BadOrigin> for DispatchError {
721 fn from(_: crate::traits::BadOrigin) -> Self {
722 Self::BadOrigin
723 }
724}
725
726#[derive(
728 Eq,
729 PartialEq,
730 Clone,
731 Copy,
732 Encode,
733 Decode,
734 DecodeWithMemTracking,
735 Debug,
736 TypeInfo,
737 MaxEncodedLen,
738)]
739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
740pub enum TokenError {
741 FundsUnavailable,
743 OnlyProvider,
746 BelowMinimum,
748 CannotCreate,
750 UnknownAsset,
752 Frozen,
754 Unsupported,
756 CannotCreateHold,
758 NotExpendable,
760 Blocked,
762}
763
764impl From<TokenError> for &'static str {
765 fn from(e: TokenError) -> &'static str {
766 match e {
767 TokenError::FundsUnavailable => "Funds are unavailable",
768 TokenError::OnlyProvider => "Account that must exist would die",
769 TokenError::BelowMinimum => "Account cannot exist with the funds that would be given",
770 TokenError::CannotCreate => "Account cannot be created",
771 TokenError::UnknownAsset => "The asset in question is unknown",
772 TokenError::Frozen => "Funds exist but are frozen",
773 TokenError::Unsupported => "Operation is not supported by the asset",
774 TokenError::CannotCreateHold => {
775 "Account cannot be created for recording amount on hold"
776 },
777 TokenError::NotExpendable => "Account that is desired to remain would die",
778 TokenError::Blocked => "Account cannot receive the assets",
779 }
780 }
781}
782
783impl From<TokenError> for DispatchError {
784 fn from(e: TokenError) -> DispatchError {
785 Self::Token(e)
786 }
787}
788
789impl From<ArithmeticError> for DispatchError {
790 fn from(e: ArithmeticError) -> DispatchError {
791 Self::Arithmetic(e)
792 }
793}
794
795impl From<TrieError> for DispatchError {
796 fn from(e: TrieError) -> DispatchError {
797 Self::Trie(e)
798 }
799}
800
801impl From<&'static str> for DispatchError {
802 fn from(err: &'static str) -> DispatchError {
803 Self::Other(err)
804 }
805}
806
807impl From<DispatchError> for &'static str {
808 fn from(err: DispatchError) -> &'static str {
809 use DispatchError::*;
810 match err {
811 Other(msg) => msg,
812 CannotLookup => "Cannot lookup",
813 BadOrigin => "Bad origin",
814 Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
815 ConsumerRemaining => "Consumer remaining",
816 NoProviders => "No providers",
817 TooManyConsumers => "Too many consumers",
818 Token(e) => e.into(),
819 Arithmetic(e) => e.into(),
820 Transactional(e) => e.into(),
821 Exhausted => "Resources exhausted",
822 Corruption => "State corrupt",
823 Unavailable => "Resource unavailable",
824 RootNotAllowed => "Root not allowed",
825 Trie(e) => e.into(),
826 }
827 }
828}
829
830impl<T> From<DispatchErrorWithPostInfo<T>> for &'static str
831where
832 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
833{
834 fn from(err: DispatchErrorWithPostInfo<T>) -> &'static str {
835 err.error.into()
836 }
837}
838
839impl traits::Printable for DispatchError {
840 fn print(&self) {
841 use DispatchError::*;
842 "DispatchError".print();
843 match self {
844 Other(err) => err.print(),
845 CannotLookup => "Cannot lookup".print(),
846 BadOrigin => "Bad origin".print(),
847 Module(ModuleError { index, error, message }) => {
848 index.print();
849 error.print();
850 if let Some(msg) = message {
851 msg.print();
852 }
853 },
854 ConsumerRemaining => "Consumer remaining".print(),
855 NoProviders => "No providers".print(),
856 TooManyConsumers => "Too many consumers".print(),
857 Token(e) => {
858 "Token error: ".print();
859 <&'static str>::from(*e).print();
860 },
861 Arithmetic(e) => {
862 "Arithmetic error: ".print();
863 <&'static str>::from(*e).print();
864 },
865 Transactional(e) => {
866 "Transactional error: ".print();
867 <&'static str>::from(*e).print();
868 },
869 Exhausted => "Resources exhausted".print(),
870 Corruption => "State corrupt".print(),
871 Unavailable => "Resource unavailable".print(),
872 RootNotAllowed => "Root not allowed".print(),
873 Trie(e) => {
874 "Trie error: ".print();
875 <&'static str>::from(*e).print();
876 },
877 }
878 }
879}
880
881impl<T> traits::Printable for DispatchErrorWithPostInfo<T>
882where
883 T: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
884{
885 fn print(&self) {
886 self.error.print();
887 "PostInfo: ".print();
888 self.post_info.print();
889 }
890}
891
892pub type DispatchOutcome = Result<(), DispatchError>;
902
903pub type ApplyExtrinsicResult =
922 Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
923
924pub type ApplyExtrinsicResultWithInfo<T> =
926 Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
927
928pub type TryRuntimeError = DispatchError;
930
931pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
934 sig: &V,
935 item: &T,
936 signer: &<V::Signer as IdentifyAccount>::AccountId,
937) -> bool {
938 struct LazyEncode<F> {
943 inner: F,
944 encoded: Option<Vec<u8>>,
945 }
946
947 impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
948 fn get(&mut self) -> &[u8] {
949 self.encoded.get_or_insert_with(&self.inner).as_slice()
950 }
951 }
952
953 sig.verify(LazyEncode { inner: || item.encode(), encoded: None }, signer)
954}
955
956#[macro_export]
974#[cfg(feature = "std")]
975macro_rules! assert_eq_error_rate {
976 ($x:expr, $y:expr, $error:expr $(,)?) => {
977 assert!(
978 ($x >= $crate::Saturating::saturating_sub($y, $error))
979 && ($x <= $crate::Saturating::saturating_add($y, $error)),
980 "{:?} != {:?} (with error rate {:?})",
981 $x,
982 $y,
983 $error,
984 );
985 };
986}
987
988#[macro_export]
991#[cfg(feature = "std")]
992macro_rules! assert_eq_error_rate_float {
993 ($x:expr, $y:expr, $error:expr $(,)?) => {
994 assert!(
995 ($x >= $y - $error) && ($x <= $y + $error),
996 "{:?} != {:?} (with error rate {:?})",
997 $x,
998 $y,
999 $error,
1000 );
1001 };
1002}
1003
1004#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, DecodeWithMemTracking)]
1007pub struct OpaqueExtrinsic(bytes::Bytes);
1008
1009impl TypeInfo for OpaqueExtrinsic {
1010 type Identity = Self;
1011 fn type_info() -> scale_info::Type {
1012 scale_info::Type::builder()
1013 .path(scale_info::Path::new("OpaqueExtrinsic", module_path!()))
1014 .composite(
1015 scale_info::build::Fields::unnamed()
1016 .field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
1017 )
1018 }
1019}
1020
1021impl OpaqueExtrinsic {
1022 pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1024 Self::decode(&mut bytes)
1025 }
1026
1027 #[deprecated = "Use `try_from_encoded_extrinsic()` instead"]
1029 pub fn from_bytes(bytes: &[u8]) -> Result<Self, codec::Error> {
1030 Self::try_from_encoded_extrinsic(bytes)
1031 }
1032
1033 pub fn from_blob(bytes: Vec<u8>) -> Self {
1035 Self(bytes.into())
1036 }
1037
1038 pub fn inner(&self) -> &[u8] {
1040 &self.0
1041 }
1042}
1043
1044impl LazyExtrinsic for OpaqueExtrinsic {
1045 fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
1046 Ok(Self(data.to_vec().into()))
1047 }
1048}
1049
1050impl core::fmt::Debug for OpaqueExtrinsic {
1051 #[cfg(feature = "std")]
1052 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1053 write!(fmt, "{}", pezsp_core::hexdisplay::HexDisplay::from(&self.0.as_ref()))
1054 }
1055
1056 #[cfg(not(feature = "std"))]
1057 fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
1058 Ok(())
1059 }
1060}
1061
1062#[cfg(feature = "serde")]
1063impl ::serde::Serialize for OpaqueExtrinsic {
1064 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
1065 where
1066 S: ::serde::Serializer,
1067 {
1068 codec::Encode::using_encoded(&self.0, |bytes| ::pezsp_core::bytes::serialize(bytes, seq))
1069 }
1070}
1071
1072#[cfg(feature = "serde")]
1073impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
1074 fn deserialize<D>(de: D) -> Result<Self, D::Error>
1075 where
1076 D: ::serde::Deserializer<'a>,
1077 {
1078 let r = ::pezsp_core::bytes::deserialize(de)?;
1079 Decode::decode(&mut &r[..])
1080 .map_err(|e| ::serde::de::Error::custom(alloc::format!("Decode error: {}", e)))
1081 }
1082}
1083
1084impl traits::ExtrinsicLike for OpaqueExtrinsic {
1085 fn is_bare(&self) -> bool {
1086 false
1087 }
1088}
1089
1090pub fn print(print: impl traits::Printable) {
1092 print.print();
1093}
1094
1095pub const fn str_array<const N: usize>(s: &str) -> [u8; N] {
1110 debug_assert!(s.len() <= N, "String literal doesn't fit in array");
1111 let mut i = 0;
1112 let mut arr = [0; N];
1113 let s = s.as_bytes();
1114 while i < s.len() {
1115 arr[i] = s[i];
1116 i += 1;
1117 }
1118 arr
1119}
1120
1121pub enum TransactionOutcome<R> {
1123 Commit(R),
1125 Rollback(R),
1127}
1128
1129impl<R> TransactionOutcome<R> {
1130 pub fn into_inner(self) -> R {
1132 match self {
1133 Self::Commit(r) => r,
1134 Self::Rollback(r) => r,
1135 }
1136 }
1137}
1138
1139#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1141pub enum ExtrinsicInclusionMode {
1142 #[default]
1144 AllExtrinsics,
1145 OnlyInherents,
1147}
1148
1149#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
1151pub struct OpaqueValue(Vec<u8>);
1152impl OpaqueValue {
1153 pub fn new(inner: Vec<u8>) -> OpaqueValue {
1155 OpaqueValue(inner)
1156 }
1157
1158 pub fn decode<T: Decode>(&self) -> Option<T> {
1160 Decode::decode(&mut &self.0[..]).ok()
1161 }
1162}
1163
1164#[macro_export]
1167#[deprecated = "Use Cow::Borrowed() instead of create_runtime_str!()"]
1168macro_rules! create_runtime_str {
1169 ( $y:expr ) => {{
1170 $crate::Cow::Borrowed($y)
1171 }};
1172}
1173#[doc(hidden)]
1175pub use alloc::borrow::Cow;
1176
1177#[deprecated = "Use String or Cow<'static, str> instead"]
1180pub type RuntimeString = alloc::string::String;
1181
1182#[cfg(test)]
1183mod tests {
1184 use crate::traits::BlakeTwo256;
1185
1186 use super::*;
1187 use codec::{Decode, Encode};
1188 use pezsp_core::{crypto::Pair, hex2array};
1189 use pezsp_io::TestExternalities;
1190 use pezsp_state_machine::create_proof_check_backend;
1191
1192 #[test]
1193 fn opaque_extrinsic_serialization() {
1194 let ex = OpaqueExtrinsic::from_blob(vec![1, 2, 3, 4]);
1195 assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
1196 }
1197
1198 #[test]
1199 fn dispatch_error_encoding() {
1200 let error = DispatchError::Module(ModuleError {
1201 index: 1,
1202 error: [2, 0, 0, 0],
1203 message: Some("error message"),
1204 });
1205 let encoded = error.encode();
1206 let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
1207 assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]);
1208 assert_eq!(
1209 decoded,
1210 DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None })
1211 );
1212 }
1213
1214 #[test]
1215 fn dispatch_error_equality() {
1216 use DispatchError::*;
1217
1218 let variants = vec![
1219 Other("foo"),
1220 Other("bar"),
1221 CannotLookup,
1222 BadOrigin,
1223 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1224 Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }),
1225 Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }),
1226 ConsumerRemaining,
1227 NoProviders,
1228 Token(TokenError::FundsUnavailable),
1229 Token(TokenError::OnlyProvider),
1230 Token(TokenError::BelowMinimum),
1231 Token(TokenError::CannotCreate),
1232 Token(TokenError::UnknownAsset),
1233 Token(TokenError::Frozen),
1234 Arithmetic(ArithmeticError::Overflow),
1235 Arithmetic(ArithmeticError::Underflow),
1236 Arithmetic(ArithmeticError::DivisionByZero),
1237 ];
1238 for (i, variant) in variants.iter().enumerate() {
1239 for (j, other_variant) in variants.iter().enumerate() {
1240 if i == j {
1241 assert_eq!(variant, other_variant);
1242 } else {
1243 assert_ne!(variant, other_variant);
1244 }
1245 }
1246 }
1247
1248 assert_eq!(
1250 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }),
1251 Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }),
1252 );
1253 }
1254
1255 #[test]
1256 fn multi_signature_ecdsa_verify_works() {
1257 let msg = &b"test-message"[..];
1258 let (pair, _) = ecdsa::Pair::generate();
1259
1260 let signature = pair.sign(&msg);
1261 assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
1262
1263 let multi_sig = MultiSignature::from(signature);
1264 let multi_signer = MultiSigner::from(pair.public());
1265 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1266 }
1267
1268 #[test]
1269 fn multi_signature_eth_verify_works() {
1270 let msg = &b"test-message"[..];
1271 let (pair, _) = ecdsa::KeccakPair::generate();
1272
1273 let signature = pair.sign(&msg);
1274 assert!(ecdsa::KeccakPair::verify(&signature, msg, &pair.public()));
1275
1276 let multi_sig = MultiSignature::Eth(signature);
1277 let multi_signer = MultiSigner::Eth(pair.public());
1278 assert!(multi_sig.verify(msg, &multi_signer.into_account()));
1279 }
1280
1281 #[test]
1282 fn multi_signer_eth_address_works() {
1283 let ecdsa_pair = ecdsa::Pair::from_seed(&[0x42; 32]);
1284 let eth_pair = ecdsa::KeccakPair::from_seed(&[0x42; 32]);
1285 let ecdsa = MultiSigner::Ecdsa(ecdsa_pair.public()).into_account();
1286 let eth = MultiSigner::Eth(eth_pair.public()).into_account();
1287
1288 assert_eq!(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(ð)[20..], &[0xEE; 12]);
1289 assert_eq!(
1290 ecdsa,
1291 hex2array!("ff241710529476ac87c67b66ccdc42f95a14b49a896164839fe675dc6f579614").into(),
1292 );
1293 assert_eq!(
1294 eth,
1295 hex2array!("2714c48edc39bc2714729e6530760d62344d6698eeeeeeeeeeeeeeeeeeeeeeee").into(),
1296 );
1297 }
1298
1299 #[test]
1300 fn execute_and_generate_proof_works() {
1301 use codec::Encode;
1302 use pezsp_state_machine::Backend;
1303 let mut ext = TestExternalities::default();
1304
1305 ext.insert(b"a".to_vec(), vec![1u8; 33]);
1306 ext.insert(b"b".to_vec(), vec![2u8; 33]);
1307 ext.insert(b"c".to_vec(), vec![3u8; 33]);
1308 ext.insert(b"d".to_vec(), vec![4u8; 33]);
1309
1310 let pre_root = *ext.backend.root();
1311 let (_, proof) = ext.execute_and_prove(|| {
1312 pezsp_io::storage::get(b"a");
1313 pezsp_io::storage::get(b"b");
1314 pezsp_io::storage::get(b"v");
1315 pezsp_io::storage::get(b"d");
1316 });
1317
1318 let compact_proof = proof.clone().into_compact_proof::<BlakeTwo256>(pre_root).unwrap();
1319 let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap();
1320
1321 println!("proof size: {:?}", proof.encoded_size());
1323 println!("compact proof size: {:?}", compact_proof.encoded_size());
1324 println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len());
1325
1326 let proof_check = create_proof_check_backend::<BlakeTwo256>(pre_root, proof).unwrap();
1328 assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]);
1329
1330 let _ = ext.execute_and_prove(|| {
1331 pezsp_io::storage::set(b"a", &vec![1u8; 44]);
1332 });
1333
1334 ext.execute_with(|| {
1337 assert_eq!(pezsp_io::storage::get(b"a").unwrap(), vec![1u8; 44]);
1338 assert_eq!(pezsp_io::storage::get(b"b").unwrap(), vec![2u8; 33]);
1339 });
1340 }
1341}
1342
1343#[cfg(test)]
1346mod pezsp_core_tests {
1347 use super::*;
1348
1349 pezsp_core::generate_feature_enabled_macro!(if_test, test, $);
1350 pezsp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
1351
1352 #[test]
1353 #[should_panic]
1354 fn generate_feature_enabled_macro_panics() {
1355 if_test!(panic!("This should panic"));
1356 }
1357
1358 #[test]
1359 fn generate_feature_enabled_macro_works() {
1360 if_not_test!(panic!("This should not panic"));
1361 }
1362}