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