referrerpolicy=no-referrer-when-downgrade

sp_runtime/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! # Substrate Runtime Primitives.
19//!
20//! This crate, among other things, contains a large library of types and utilities that are used in
21//! the Substrate runtime, but are not particularly `FRAME`-oriented.
22//!
23//! ## Block, Header and Extrinsics
24//!
25//! Most notable, this crate contains some of the types and trait that enable important
26//! communication between the client and the runtime. This includes:
27//!
28//! - A set of traits to declare what any block/header/extrinsic type should provide.
29//! 	- [`traits::Block`], [`traits::Header`], [`traits::ExtrinsicLike`]
30//! - A set of types that implement these traits, whilst still providing a high degree of
31//!   configurability via generics.
32//! 	- [`generic::Block`], [`generic::Header`], [`generic::UncheckedExtrinsic`] and
33//!    [`generic::CheckedExtrinsic`]
34//!
35//! ## Runtime API Types
36//!
37//! This crate also contains some types that are often used in conjuncture with Runtime APIs. Most
38//! notable:
39//!
40//! - [`ApplyExtrinsicResult`], and [`DispatchOutcome`], which dictate how the client and runtime
41//!   communicate about the success or failure of an extrinsic.
42//! - [`transaction_validity`], which dictates how the client and runtime communicate about the
43//!  validity of an extrinsic while still in the transaction-queue.
44
45#![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
99// Re-export Multiaddress
100pub use multiaddress::MultiAddress;
101
102use proving_trie::TrieError;
103
104/// Re-export these since they're only "kind of" generic.
105pub use generic::{Digest, DigestItem};
106
107pub use sp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
108/// Re-export this since it's part of the API of this crate.
109pub use sp_core::{
110	bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec},
111	crypto::{key_types, AccountId32, CryptoType, CryptoTypeId, KeyTypeId},
112	TypeId,
113};
114/// Re-export bounded_vec and bounded_btree_map macros only when std is enabled.
115#[cfg(feature = "std")]
116pub use sp_core::{bounded_btree_map, bounded_vec};
117
118/// Re-export `Debug`, to avoid dependency clutter.
119pub use core::fmt::Debug;
120
121/// Re-export big_uint stuff.
122pub use sp_arithmetic::biguint;
123/// Re-export 128 bit helpers.
124pub use sp_arithmetic::helpers_128bit;
125/// Re-export top-level arithmetic stuff.
126pub 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};
131/// Re-export this since it's part of the API of this crate.
132pub use sp_weights::Weight;
133
134pub use either::Either;
135
136/// The number of bytes of the module-specific `error` field defined in [`ModuleError`].
137/// In FRAME, this is the maximum encoded size of a pallet error type.
138pub const MAX_MODULE_ERROR_ENCODED_SIZE: usize = 4;
139
140/// An abstraction over justification for a block's validity under a consensus algorithm.
141///
142/// Essentially a finality proof. The exact formulation will vary between consensus
143/// algorithms. In the case where there are multiple valid proofs, inclusion within
144/// the block itself would allow swapping justifications to change the block's hash
145/// (and thus fork the chain). Sending a `Justification` alongside a block instead
146/// bypasses this problem.
147///
148/// Each justification is provided as an encoded blob, and is tagged with an ID
149/// to identify the consensus engine that generated the proof (we might have
150/// multiple justifications from different engines for the same block).
151pub type Justification = (ConsensusEngineId, EncodedJustification);
152
153/// The encoded justification specific to a consensus engine.
154pub type EncodedJustification = Vec<u8>;
155
156/// Collection of justifications for a given block, multiple justifications may
157/// be provided by different consensus engines for the same block.
158#[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	/// Create a new `Justifications` instance with the given justifications.
164	pub fn new(justifications: Vec<Justification>) -> Self {
165		Self(justifications)
166	}
167
168	/// Return an iterator over the justifications.
169	pub fn iter(&self) -> impl Iterator<Item = &Justification> {
170		self.0.iter()
171	}
172
173	/// Append a justification. Returns false if a justification with the same
174	/// `ConsensusEngineId` already exists, in which case the justification is
175	/// not inserted.
176	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	/// Return the encoded justification for the given consensus engine, if it
185	/// exists.
186	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	/// Remove the encoded justification for the given consensus engine, if it exists.
191	pub fn remove(&mut self, engine_id: ConsensusEngineId) {
192		self.0.retain(|j| j.0 != engine_id)
193	}
194
195	/// Return a copy of the encoded justification for the given consensus
196	/// engine, if it exists.
197	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/// Complex storage builder stuff.
224#[cfg(feature = "std")]
225pub trait BuildStorage {
226	/// Build the storage out of this builder.
227	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	/// Assimilate the storage for this module into pre-existing overlays.
233	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
262/// Consensus engine unique ID.
263pub type ConsensusEngineId = [u8; 4];
264
265/// Signature verify that can work with any known signature types.
266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
267#[derive(
268	Eq, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, Debug, TypeInfo,
269)]
270pub enum MultiSignature {
271	/// An Ed25519 signature.
272	Ed25519(ed25519::Signature),
273	/// An Sr25519 signature.
274	Sr25519(sr25519::Signature),
275	/// An ECDSA/SECP256k1 signature.
276	Ecdsa(ecdsa::Signature),
277	/// An ECDSA/SECP256k1 signature but with a different address derivation.
278	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/// Public key for any known crypto algorithm.
333#[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	/// An Ed25519 identity.
339	Ed25519(ed25519::Public),
340	/// An Sr25519 identity.
341	Sr25519(sr25519::Public),
342	/// An SECP256k1/ECDSA identity (actually, the Blake2 hash of the compressed pub key).
343	Ecdsa(ecdsa::Public),
344	/// Same as `Ecdsa` but its account id is derived based off its eth address instead of its
345	/// pubkey.
346	///
347	/// This is important so that the address matches the address to address mapping in
348	/// `pallet_revive`. This means that the same public key controls two accounts. But
349	/// this is already the case due to `pallet_revive`'s address mapping.
350	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
364/// NOTE: This implementations is required by `SimpleAddressDeterminer`,
365/// we convert the hash into some AccountId, it's fine to use any scheme.
366impl<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				// It is important that the account id is based off the eth address rather
392				// than its pubkey. This is because in many cases we don't know the pubkey
393				// of an eth account.
394				let eth_address = &sp_io::hashing::keccak_256(who.as_ref())[12..];
395				// This is by convention: `pallet_revive` maps eth addresses to account ids
396				// by filling up the additional 12 bytes with 0xEE.
397				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				// Reject high-S signatures (BIP-62 malleability protection)
478				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				// Reject high-S signatures (EIP-2 / BIP-62 malleability protection)
488				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/// Signature verify that can work with any known signature types..
502#[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
540/// This is the legacy return type of `Dispatchable`. It is still exposed for compatibility reasons.
541/// The new return type is `DispatchResultWithInfo`. FRAME runtimes should use
542/// `frame_support::dispatch::DispatchResult`.
543pub type DispatchResult = core::result::Result<(), DispatchError>;
544
545/// Return type of a `Dispatchable` which contains the `DispatchResult` and additional information
546/// about the `Dispatchable` that is only known post dispatch.
547pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
548
549/// Reason why a pallet call failed.
550#[derive(
551	Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
552)]
553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
554pub struct ModuleError {
555	/// Module index, matching the metadata module index.
556	pub index: u8,
557	/// Module specific error value.
558	pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE],
559	/// Optional error message.
560	#[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/// Errors related to transactional storage layers.
572#[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	/// Too many transactional layers have been spawned.
587	LimitReached,
588	/// A transactional layer was expected, but does not exist.
589	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/// Reason why a dispatch call failed.
608#[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	/// Some error occurred.
623	Other(
624		#[codec(skip)]
625		#[cfg_attr(feature = "serde", serde(skip_deserializing))]
626		&'static str,
627	),
628	/// Failed to lookup some data.
629	CannotLookup,
630	/// A bad origin.
631	BadOrigin,
632	/// A custom error in a module.
633	Module(ModuleError),
634	/// At least one consumer is remaining so the account cannot be destroyed.
635	ConsumerRemaining,
636	/// There are no providers so the account cannot be created.
637	NoProviders,
638	/// There are too many consumers so the account cannot be created.
639	TooManyConsumers,
640	/// An error to do with tokens.
641	Token(TokenError),
642	/// An arithmetic error.
643	Arithmetic(ArithmeticError),
644	/// The number of transactional layers has been reached, or we are not in a transactional
645	/// layer.
646	Transactional(TransactionalError),
647	/// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate.
648	Exhausted,
649	/// The state is corrupt; this is generally not going to fix itself.
650	Corruption,
651	/// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later.
652	Unavailable,
653	/// Root origin is not allowed.
654	RootNotAllowed,
655	/// An error with tries.
656	Trie(TrieError),
657}
658
659/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about
660/// the `Dispatchable` that is only known post dispatch.
661#[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	/// Additional information about the `Dispatchable` which is only known post dispatch.
667	pub post_info: Info,
668	/// The actual `DispatchResult` indicating whether the dispatch was successful.
669	pub error: DispatchError,
670}
671
672impl DispatchError {
673	/// Return the same error but without the attached message.
674	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/// Description of what went wrong when trying to complete an operation on a token.
707#[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	/// Funds are unavailable.
722	FundsUnavailable,
723	/// Some part of the balance gives the only provider reference to the account and thus cannot
724	/// be (re)moved.
725	OnlyProvider,
726	/// Account cannot exist with the funds that would be given.
727	BelowMinimum,
728	/// Account cannot be created.
729	CannotCreate,
730	/// The asset in question is unknown.
731	UnknownAsset,
732	/// Funds exist but are frozen.
733	Frozen,
734	/// Operation is not supported by the asset.
735	Unsupported,
736	/// Account cannot be created for a held balance.
737	CannotCreateHold,
738	/// Withdrawal would cause unwanted loss of account.
739	NotExpendable,
740	/// Account cannot receive the assets.
741	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
872/// This type specifies the outcome of dispatching a call to a module.
873///
874/// In case of failure an error specific to the module is returned.
875///
876/// Failure of the module call dispatching doesn't invalidate the extrinsic and it is still included
877/// in the block, therefore all state changes performed by the dispatched call are still persisted.
878///
879/// For example, if the dispatching of an extrinsic involves inclusion fee payment then these
880/// changes are going to be preserved even if the call dispatched failed.
881pub type DispatchOutcome = Result<(), DispatchError>;
882
883/// The result of applying of an extrinsic.
884///
885/// This type is typically used in the context of `BlockBuilder` to signal that the extrinsic
886/// in question cannot be included.
887///
888/// A block containing extrinsics that have a negative inclusion outcome is invalid. A negative
889/// result can only occur during the block production, where such extrinsics are detected and
890/// removed from the block that is being created and the transaction pool.
891///
892/// To rehash: every extrinsic in a valid block must return a positive `ApplyExtrinsicResult`.
893///
894/// Examples of reasons preventing inclusion in a block:
895/// - More block weight is required to process the extrinsic than is left in the block being built.
896///   This doesn't necessarily mean that the extrinsic is invalid, since it can still be included in
897///   the next block if it has enough spare weight available.
898/// - The sender doesn't have enough funds to pay the transaction inclusion fee. Including such a
899///   transaction in the block doesn't make sense.
900/// - The extrinsic supplied a bad signature. This transaction won't become valid ever.
901pub type ApplyExtrinsicResult =
902	Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
903
904/// Same as `ApplyExtrinsicResult` but augmented with `PostDispatchInfo` on success.
905pub type ApplyExtrinsicResultWithInfo<T> =
906	Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
907
908/// The error type used as return type in try runtime hooks.
909pub type TryRuntimeError = DispatchError;
910
911/// Verify a signature on an encoded value in a lazy manner. This can be
912/// an optimization if the signature scheme has an "unsigned" escape hash.
913pub 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	// The `Lazy<T>` trait expresses something like `X: FnMut<Output = for<'a> &'a T>`.
919	// unfortunately this is a lifetime relationship that can't
920	// be expressed without generic associated types, better unification of HRTBs in type position,
921	// and some kind of integration into the Fn* traits.
922	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/// Checks that `$x` is equal to `$y` with an error rate of `$error`.
937///
938/// # Example
939///
940/// ```rust
941/// # fn main() {
942/// sp_runtime::assert_eq_error_rate!(10, 10, 0);
943/// sp_runtime::assert_eq_error_rate!(10, 11, 1);
944/// sp_runtime::assert_eq_error_rate!(12, 10, 2);
945/// # }
946/// ```
947///
948/// ```rust,should_panic
949/// # fn main() {
950/// sp_runtime::assert_eq_error_rate!(12, 10, 1);
951/// # }
952/// ```
953#[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/// Same as [`assert_eq_error_rate`], but intended to be used with floating point number, or
969/// generally those who do not have over/underflow potentials.
970#[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/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized
985/// correctly.
986#[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	/// Convert an encoded extrinsic to an `OpaqueExtrinsic`.
1003	pub fn try_from_encoded_extrinsic(mut bytes: &[u8]) -> Result<Self, codec::Error> {
1004		Self::decode(&mut bytes)
1005	}
1006
1007	/// Convert an encoded extrinsic to an `OpaqueExtrinsic`.
1008	#[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	/// Create a new instance of `OpaqueExtrinsic` from a `Vec<u8>`.
1014	pub fn from_blob(bytes: Vec<u8>) -> Self {
1015		Self(bytes.into())
1016	}
1017
1018	/// Get the actual blob.
1019	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
1070/// Print something that implements `Printable` from the runtime.
1071pub fn print(print: impl traits::Printable) {
1072	print.print();
1073}
1074
1075/// Utility function to declare string literals backed by an array of length N.
1076///
1077/// The input can be shorter than N, in that case the end of the array is padded with zeros.
1078///
1079/// [`str_array`] is useful when converting strings that end up in the storage as fixed size arrays
1080/// or in const contexts where static data types have strings that could also end up in the storage.
1081///
1082/// # Example
1083///
1084/// ```rust
1085/// # use sp_runtime::str_array;
1086/// const MY_STR: [u8; 6] = str_array("data");
1087/// assert_eq!(MY_STR, *b"data\0\0");
1088/// ```
1089pub 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
1101/// Describes on what should happen with a storage transaction.
1102pub enum TransactionOutcome<R> {
1103	/// Commit the transaction.
1104	Commit(R),
1105	/// Rollback the transaction.
1106	Rollback(R),
1107}
1108
1109impl<R> TransactionOutcome<R> {
1110	/// Convert into the inner type.
1111	pub fn into_inner(self) -> R {
1112		match self {
1113			Self::Commit(r) => r,
1114			Self::Rollback(r) => r,
1115		}
1116	}
1117}
1118
1119/// Confines the kind of extrinsics that can be included in a block.
1120#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)]
1121pub enum ExtrinsicInclusionMode {
1122	/// All extrinsics are allowed to be included in this block.
1123	#[default]
1124	AllExtrinsics,
1125	/// Inherents are allowed to be included.
1126	OnlyInherents,
1127}
1128
1129/// Simple blob that hold a value in an encoded form without committing to its type.
1130#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
1131pub struct OpaqueValue(Vec<u8>);
1132impl OpaqueValue {
1133	/// Create a new `OpaqueValue` using the given encoded representation.
1134	pub fn new(inner: Vec<u8>) -> OpaqueValue {
1135		OpaqueValue(inner)
1136	}
1137
1138	/// Try to decode this `OpaqueValue` into the given concrete type.
1139	pub fn decode<T: Decode>(&self) -> Option<T> {
1140		Decode::decode(&mut &self.0[..]).ok()
1141	}
1142}
1143
1144// TODO: Remove in future versions and clean up `parse_str_literal` in `sp-version-proc-macro`
1145/// Deprecated `Cow::Borrowed()` wrapper.
1146#[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// TODO: Re-export for ^ macro `create_runtime_str`, should be removed once macro is gone
1154#[doc(hidden)]
1155pub use alloc::borrow::Cow;
1156
1157// TODO: Remove in future versions
1158/// Deprecated alias to improve upgrade experience
1159#[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		// Ignores `message` field in `Module` variant.
1229		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	/// Helper: compute high-S malleable variant of a 65-byte ECDSA signature.
1262	/// Returns `s' = order - s` with `v' = v ^ 1`.
1263	pub(crate) fn make_high_s_signature(sig: &[u8; 65]) -> [u8; 65] {
1264		// secp256k1 curve order N
1265		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		// Low-S signature verifies
1300		let multi_sig = MultiSignature::from(signature);
1301		assert!(multi_sig.verify(msg, &account));
1302
1303		// Construct high-S malleable variant
1304		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		// Low-S signature verifies
1323		let multi_sig = MultiSignature::Eth(signature);
1324		assert!(multi_sig.verify(msg, &account));
1325
1326		// Construct high-S malleable variant
1327		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(&eth)[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		// just an example of how you'd inspect the size of the proof.
1377		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		// create a new trie-backed from the proof and make sure it contains everything
1382		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		// ensure that these changes are propagated to the backend.
1390
1391		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// NOTE: we have to test the sp_core stuff also from a different crate to check that the macro
1399// can access the sp_core crate.
1400#[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}