sp_core/
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//! Shareable Substrate types.
19
20#![warn(missing_docs)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23/// Initialize a key-value collection from array.
24///
25/// Creates a vector of given pairs and calls `collect` on the iterator from it.
26/// Can be used to create a `HashMap`.
27#[macro_export]
28macro_rules! map {
29	($( $name:expr => $value:expr ),* $(,)? ) => (
30		vec![ $( ( $name, $value ) ),* ].into_iter().collect()
31	);
32}
33
34extern crate alloc;
35
36use alloc::vec::Vec;
37#[doc(hidden)]
38pub use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
39use core::ops::Deref;
40use scale_info::TypeInfo;
41#[cfg(feature = "serde")]
42pub use serde;
43#[cfg(feature = "serde")]
44use serde::{Deserialize, Serialize};
45use sp_runtime_interface::pass_by::{PassByEnum, PassByInner};
46
47pub use sp_debug_derive::RuntimeDebug;
48
49#[cfg(feature = "serde")]
50pub use impl_serde::serialize as bytes;
51
52#[deprecated(
53	since = "27.0.0",
54	note = "`sp-crypto-hashing` re-exports will be removed after June 2024. Use `sp-crypto-hashing` instead."
55)]
56pub use sp_crypto_hashing::{self as hashing, *};
57
58pub mod const_hex2array;
59pub mod crypto;
60pub mod hexdisplay;
61pub use paste;
62mod address_uri;
63pub mod defer;
64pub mod hash;
65#[cfg(feature = "std")]
66mod hasher;
67pub mod offchain;
68pub mod testing;
69#[cfg(feature = "std")]
70pub mod traits;
71pub mod uint;
72
73#[cfg(feature = "bandersnatch-experimental")]
74pub mod bandersnatch;
75#[cfg(feature = "bls-experimental")]
76pub mod bls;
77pub mod crypto_bytes;
78pub mod ecdsa;
79pub mod ed25519;
80pub mod paired_crypto;
81pub mod sr25519;
82
83#[cfg(feature = "bls-experimental")]
84pub use bls::{bls377, bls381};
85#[cfg(feature = "bls-experimental")]
86pub use paired_crypto::{ecdsa_bls377, ecdsa_bls381};
87
88pub use self::{
89	hash::{convert_hash, H160, H256, H512},
90	uint::{U256, U512},
91};
92pub use crypto::{ByteArray, DeriveJunction, Pair, Public};
93
94#[cfg(feature = "std")]
95pub use self::hasher::blake2::Blake2Hasher;
96#[cfg(feature = "std")]
97pub use self::hasher::keccak::KeccakHasher;
98pub use hash_db::Hasher;
99
100pub use bounded_collections as bounded;
101#[cfg(feature = "std")]
102pub use bounded_collections::{bounded_btree_map, bounded_vec};
103pub use bounded_collections::{
104	parameter_types, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstInt,
105	ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, ConstUint, Get, GetDefault, TryCollect,
106	TypedGet,
107};
108pub use sp_storage as storage;
109
110#[doc(hidden)]
111pub use sp_std;
112
113/// Hex-serialized shim for `Vec<u8>`.
114#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))]
116pub struct Bytes(#[cfg_attr(feature = "serde", serde(with = "bytes"))] pub Vec<u8>);
117
118impl From<Vec<u8>> for Bytes {
119	fn from(s: Vec<u8>) -> Self {
120		Bytes(s)
121	}
122}
123
124impl From<OpaqueMetadata> for Bytes {
125	fn from(s: OpaqueMetadata) -> Self {
126		Bytes(s.0)
127	}
128}
129
130impl Deref for Bytes {
131	type Target = [u8];
132	fn deref(&self) -> &[u8] {
133		&self.0[..]
134	}
135}
136
137impl codec::WrapperTypeEncode for Bytes {}
138
139impl codec::WrapperTypeDecode for Bytes {
140	type Wrapped = Vec<u8>;
141}
142
143#[cfg(feature = "std")]
144impl alloc::str::FromStr for Bytes {
145	type Err = bytes::FromHexError;
146
147	fn from_str(s: &str) -> Result<Self, Self::Err> {
148		bytes::from_hex(s).map(Bytes)
149	}
150}
151
152/// Stores the encoded `RuntimeMetadata` for the native side as opaque type.
153#[derive(Encode, Decode, PartialEq, TypeInfo)]
154pub struct OpaqueMetadata(Vec<u8>);
155
156impl OpaqueMetadata {
157	/// Creates a new instance with the given metadata blob.
158	pub fn new(metadata: Vec<u8>) -> Self {
159		OpaqueMetadata(metadata)
160	}
161}
162
163impl Deref for OpaqueMetadata {
164	type Target = Vec<u8>;
165
166	fn deref(&self) -> &Self::Target {
167		&self.0
168	}
169}
170
171/// Simple blob to hold a `PeerId` without committing to its format.
172#[derive(
173	Default,
174	Clone,
175	Eq,
176	PartialEq,
177	Ord,
178	PartialOrd,
179	Encode,
180	Decode,
181	DecodeWithMemTracking,
182	RuntimeDebug,
183	PassByInner,
184	TypeInfo,
185)]
186#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
187pub struct OpaquePeerId(pub Vec<u8>);
188
189impl OpaquePeerId {
190	/// Create new `OpaquePeerId`
191	pub fn new(vec: Vec<u8>) -> Self {
192		OpaquePeerId(vec)
193	}
194}
195
196/// Provide a simple 4 byte identifier for a type.
197pub trait TypeId {
198	/// Simple 4 byte identifier.
199	const TYPE_ID: [u8; 4];
200}
201
202/// A log level matching the one from `log` crate.
203///
204/// Used internally by `sp_io::logging::log` method.
205#[derive(Encode, Decode, PassByEnum, Copy, Clone)]
206pub enum LogLevel {
207	/// `Error` log level.
208	Error = 1_isize,
209	/// `Warn` log level.
210	Warn = 2_isize,
211	/// `Info` log level.
212	Info = 3_isize,
213	/// `Debug` log level.
214	Debug = 4_isize,
215	/// `Trace` log level.
216	Trace = 5_isize,
217}
218
219impl From<u32> for LogLevel {
220	fn from(val: u32) -> Self {
221		match val {
222			x if x == LogLevel::Warn as u32 => LogLevel::Warn,
223			x if x == LogLevel::Info as u32 => LogLevel::Info,
224			x if x == LogLevel::Debug as u32 => LogLevel::Debug,
225			x if x == LogLevel::Trace as u32 => LogLevel::Trace,
226			_ => LogLevel::Error,
227		}
228	}
229}
230
231impl From<log::Level> for LogLevel {
232	fn from(l: log::Level) -> Self {
233		use log::Level::*;
234		match l {
235			Error => Self::Error,
236			Warn => Self::Warn,
237			Info => Self::Info,
238			Debug => Self::Debug,
239			Trace => Self::Trace,
240		}
241	}
242}
243
244impl From<LogLevel> for log::Level {
245	fn from(l: LogLevel) -> Self {
246		use self::LogLevel::*;
247		match l {
248			Error => Self::Error,
249			Warn => Self::Warn,
250			Info => Self::Info,
251			Debug => Self::Debug,
252			Trace => Self::Trace,
253		}
254	}
255}
256
257/// Log level filter that expresses which log levels should be filtered.
258///
259/// This enum matches the [`log::LevelFilter`] enum.
260#[derive(Encode, Decode, PassByEnum, Copy, Clone)]
261pub enum LogLevelFilter {
262	/// `Off` log level filter.
263	Off = 0_isize,
264	/// `Error` log level filter.
265	Error = 1_isize,
266	/// `Warn` log level filter.
267	Warn = 2_isize,
268	/// `Info` log level filter.
269	Info = 3_isize,
270	/// `Debug` log level filter.
271	Debug = 4_isize,
272	/// `Trace` log level filter.
273	Trace = 5_isize,
274}
275
276impl From<LogLevelFilter> for log::LevelFilter {
277	fn from(l: LogLevelFilter) -> Self {
278		use self::LogLevelFilter::*;
279		match l {
280			Off => Self::Off,
281			Error => Self::Error,
282			Warn => Self::Warn,
283			Info => Self::Info,
284			Debug => Self::Debug,
285			Trace => Self::Trace,
286		}
287	}
288}
289
290impl From<log::LevelFilter> for LogLevelFilter {
291	fn from(l: log::LevelFilter) -> Self {
292		use log::LevelFilter::*;
293		match l {
294			Off => Self::Off,
295			Error => Self::Error,
296			Warn => Self::Warn,
297			Info => Self::Info,
298			Debug => Self::Debug,
299			Trace => Self::Trace,
300		}
301	}
302}
303
304/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`.
305///
306/// When Substrate calls into Wasm it expects a fixed signature for functions exported
307/// from the Wasm blob. The return value of this signature is always a `u64`.
308/// This `u64` stores the pointer to the encoded return value and the length of this encoded value.
309/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length.
310#[cfg(not(feature = "std"))]
311pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 {
312	let encoded = value.encode();
313
314	let ptr = encoded.as_ptr() as u64;
315	let length = encoded.len() as u64;
316	let res = ptr | (length << 32);
317
318	// Leak the output vector to avoid it being freed.
319	// This is fine in a WASM context since the heap
320	// will be discarded after the call.
321	core::mem::forget(encoded);
322
323	res
324}
325
326/// The void type - it cannot exist.
327// Oh rust, you crack me up...
328#[derive(
329	Clone,
330	Decode,
331	DecodeWithMemTracking,
332	Encode,
333	Eq,
334	PartialEq,
335	RuntimeDebug,
336	TypeInfo,
337	MaxEncodedLen,
338)]
339pub enum Void {}
340
341/// Macro for creating `Maybe*` marker traits.
342///
343/// Such a maybe-marker trait requires the given bound when `feature = std` and doesn't require
344/// the bound on `no_std`. This is useful for situations where you require that a type implements
345/// a certain trait with `feature = std`, but not on `no_std`.
346///
347/// # Example
348///
349/// ```
350/// sp_core::impl_maybe_marker! {
351///     /// A marker for a type that implements `Debug` when `feature = std`.
352///     trait MaybeDebug: std::fmt::Debug;
353///     /// A marker for a type that implements `Debug + Display` when `feature = std`.
354///     trait MaybeDebugDisplay: std::fmt::Debug, std::fmt::Display;
355/// }
356/// ```
357#[macro_export]
358macro_rules! impl_maybe_marker {
359	(
360		$(
361			$(#[$doc:meta] )+
362			trait $trait_name:ident: $( $trait_bound:path ),+;
363		)+
364	) => {
365		$(
366			$(#[$doc])+
367			#[cfg(feature = "std")]
368			pub trait $trait_name: $( $trait_bound + )+ {}
369			#[cfg(feature = "std")]
370			impl<T: $( $trait_bound + )+> $trait_name for T {}
371
372			$(#[$doc])+
373			#[cfg(not(feature = "std"))]
374			pub trait $trait_name {}
375			#[cfg(not(feature = "std"))]
376			impl<T> $trait_name for T {}
377		)+
378	}
379}
380
381/// Macro for creating `Maybe*` marker traits.
382///
383/// Such a maybe-marker trait requires the given bound when either `feature = std` or `feature =
384/// serde` is activated.
385///
386/// # Example
387///
388/// ```
389/// sp_core::impl_maybe_marker_std_or_serde! {
390///     /// A marker for a type that implements `Debug` when `feature = serde` or `feature = std`.
391///     trait MaybeDebug: std::fmt::Debug;
392///     /// A marker for a type that implements `Debug + Display` when `feature = serde` or `feature = std`.
393///     trait MaybeDebugDisplay: std::fmt::Debug, std::fmt::Display;
394/// }
395/// ```
396#[macro_export]
397macro_rules! impl_maybe_marker_std_or_serde {
398	(
399		$(
400			$(#[$doc:meta] )+
401			trait $trait_name:ident: $( $trait_bound:path ),+;
402		)+
403	) => {
404		$(
405			$(#[$doc])+
406			#[cfg(any(feature = "serde", feature = "std"))]
407			pub trait $trait_name: $( $trait_bound + )+ {}
408			#[cfg(any(feature = "serde", feature = "std"))]
409			impl<T: $( $trait_bound + )+> $trait_name for T {}
410
411			$(#[$doc])+
412			#[cfg(not(any(feature = "serde", feature = "std")))]
413			pub trait $trait_name {}
414			#[cfg(not(any(feature = "serde", feature = "std")))]
415			impl<T> $trait_name for T {}
416		)+
417	}
418}
419
420/// The maximum number of bytes that can be allocated at one time.
421// The maximum possible allocation size was chosen rather arbitrary, 32 MiB should be enough for
422// everybody.
423pub const MAX_POSSIBLE_ALLOCATION: u32 = 33554432; // 2^25 bytes, 32 MiB
424
425/// Generates a macro for checking if a certain feature is enabled.
426///
427/// These feature checking macros can be used to conditionally enable/disable code in a dependent
428/// crate based on a feature in the crate where the macro is called.
429///
430/// # Example
431///```
432/// sp_core::generate_feature_enabled_macro!(check_std_is_enabled, feature = "std", $);
433/// sp_core::generate_feature_enabled_macro!(check_std_or_serde_is_enabled, any(feature = "std", feature = "serde"), $);
434///
435/// // All the code passed to the macro will then conditionally compiled based on the features
436/// // activated for the crate where the macro was generated.
437/// check_std_is_enabled! {
438///     struct StdEnabled;
439/// }
440///```
441#[macro_export]
442// We need to skip formatting this macro because of this bug:
443// https://github.com/rust-lang/rustfmt/issues/5283
444#[rustfmt::skip]
445macro_rules! generate_feature_enabled_macro {
446	( $macro_name:ident, $feature_name:meta, $d:tt ) => {
447		$crate::paste::paste!{
448			///
449			#[cfg($feature_name)]
450			#[macro_export]
451			macro_rules! [<_ $macro_name>] {
452				( $d ( $d input:tt )* ) => {
453					$d ( $d input )*
454				}
455			}
456
457			///
458 			#[cfg(not($feature_name))]
459			#[macro_export]
460			macro_rules! [<_ $macro_name>] {
461				( $d ( $d input:tt )* ) => {};
462			}
463
464			/// Enable/disable the given code depending on
465			#[doc = concat!("`", stringify!($feature_name), "`")]
466			/// being enabled for the crate or not.
467			///
468			/// # Example
469			///
470			/// ```nocompile
471			/// // Will add the code depending on the feature being enabled or not.
472			#[doc = concat!(stringify!($macro_name), "!( println!(\"Hello\") )")]
473			/// ```
474			// https://github.com/rust-lang/rust/pull/52234
475 			pub use [<_ $macro_name>] as $macro_name;
476		}
477	};
478}
479
480#[cfg(test)]
481mod tests {
482	use super::*;
483
484	generate_feature_enabled_macro!(if_test, test, $);
485	generate_feature_enabled_macro!(if_not_test, not(test), $);
486
487	#[test]
488	#[should_panic]
489	fn generate_feature_enabled_macro_panics() {
490		if_test!(panic!("This should panic"));
491	}
492
493	#[test]
494	fn generate_feature_enabled_macro_works() {
495		if_not_test!(panic!("This should not panic"));
496	}
497}