sp_application_crypto/
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//! Traits and macros for constructing application specific strongly typed crypto wrappers.
19
20#![warn(missing_docs)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23extern crate alloc;
24
25pub use sp_core::crypto::{key_types, CryptoTypeId, DeriveJunction, KeyTypeId, Ss58Codec};
26#[doc(hidden)]
27pub use sp_core::crypto::{DeriveError, Pair, SecretStringError};
28#[doc(hidden)]
29pub use sp_core::{
30	self,
31	crypto::{ByteArray, CryptoType, Derive, IsWrappedBy, Public, Signature, UncheckedFrom, Wraps},
32	RuntimeDebug,
33};
34
35#[doc(hidden)]
36pub use alloc::vec::Vec;
37#[doc(hidden)]
38pub use codec;
39#[doc(hidden)]
40pub use core::ops::Deref;
41#[doc(hidden)]
42pub use scale_info;
43#[doc(hidden)]
44#[cfg(feature = "serde")]
45pub use serde;
46
47#[cfg(feature = "bandersnatch-experimental")]
48pub mod bandersnatch;
49#[cfg(feature = "bls-experimental")]
50pub mod bls381;
51pub mod ecdsa;
52#[cfg(feature = "bls-experimental")]
53pub mod ecdsa_bls381;
54pub mod ed25519;
55pub mod sr25519;
56mod traits;
57
58pub use traits::*;
59
60/// Declares `Public`, `Pair` and `Signature` types which are functionally equivalent
61/// to the corresponding types defined by `$module` but are new application-specific
62/// types whose identifier is `$key_type`.
63///
64/// ```rust
65/// # use sp_application_crypto::{app_crypto, ed25519, KeyTypeId};
66/// // Declare a new set of crypto types using ed25519 logic that identifies as `KeyTypeId`
67/// // of value `b"fuba"`.
68/// app_crypto!(ed25519, KeyTypeId(*b"fuba"));
69/// ```
70#[cfg(feature = "full_crypto")]
71#[macro_export]
72macro_rules! app_crypto {
73	($module:ident, $key_type:expr) => {
74		$crate::app_crypto_public_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID);
75		$crate::app_crypto_public_common!(
76			$module::Public,
77			$module::Signature,
78			$key_type,
79			$module::CRYPTO_ID
80		);
81		$crate::app_crypto_signature_full_crypto!(
82			$module::Signature,
83			$key_type,
84			$module::CRYPTO_ID
85		);
86		$crate::app_crypto_signature_common!($module::Signature, $key_type);
87		$crate::app_crypto_pair_common!($module::Pair, $key_type, $module::CRYPTO_ID);
88	};
89}
90
91/// Declares `Public`, `Pair` and `Signature` types which are functionally equivalent
92/// to the corresponding types defined by `$module` but that are new application-specific
93/// types whose identifier is `$key_type`.
94///
95/// ```rust
96/// # use sp_application_crypto::{app_crypto, ed25519, KeyTypeId};
97/// // Declare a new set of crypto types using ed25519 logic that identifies as `KeyTypeId`
98/// // of value `b"fuba"`.
99/// app_crypto!(ed25519, KeyTypeId(*b"fuba"));
100/// ```
101#[cfg(not(feature = "full_crypto"))]
102#[macro_export]
103macro_rules! app_crypto {
104	($module:ident, $key_type:expr) => {
105		$crate::app_crypto_public_not_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID);
106		$crate::app_crypto_public_common!(
107			$module::Public,
108			$module::Signature,
109			$key_type,
110			$module::CRYPTO_ID
111		);
112		$crate::app_crypto_signature_not_full_crypto!(
113			$module::Signature,
114			$key_type,
115			$module::CRYPTO_ID
116		);
117		$crate::app_crypto_signature_common!($module::Signature, $key_type);
118		$crate::app_crypto_pair_common!($module::Pair, $key_type, $module::CRYPTO_ID);
119	};
120}
121
122/// Declares `Pair` type which is functionally equivalent to `$pair`, but is
123/// new application-specific type whose identifier is `$key_type`.
124/// It is a common part shared between full_crypto and non full_crypto environments.
125#[macro_export]
126macro_rules! app_crypto_pair_common {
127	($pair:ty, $key_type:expr, $crypto_type:expr) => {
128		$crate::wrap! {
129			/// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App.
130			#[derive(Clone)]
131			pub struct Pair($pair);
132		}
133
134		impl $crate::CryptoType for Pair {
135			type Pair = Pair;
136		}
137
138		impl $crate::Pair for Pair {
139			type Public = Public;
140			type Seed = <$pair as $crate::Pair>::Seed;
141			type Signature = Signature;
142
143			$crate::app_crypto_pair_functions_if_std!($pair);
144			$crate::app_crypto_pair_functions_if_full_crypto!($pair);
145
146			fn from_phrase(
147				phrase: &str,
148				password: Option<&str>,
149			) -> Result<(Self, Self::Seed), $crate::SecretStringError> {
150				<$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1))
151			}
152			fn derive<Iter: Iterator<Item = $crate::DeriveJunction>>(
153				&self,
154				path: Iter,
155				seed: Option<Self::Seed>,
156			) -> Result<(Self, Option<Self::Seed>), $crate::DeriveError> {
157				self.0.derive(path, seed).map(|x| (Self(x.0), x.1))
158			}
159			fn from_seed(seed: &Self::Seed) -> Self {
160				Self(<$pair>::from_seed(seed))
161			}
162			fn from_seed_slice(seed: &[u8]) -> Result<Self, $crate::SecretStringError> {
163				<$pair>::from_seed_slice(seed).map(Self)
164			}
165			fn verify<M: AsRef<[u8]>>(
166				sig: &Self::Signature,
167				message: M,
168				pubkey: &Self::Public,
169			) -> bool {
170				<$pair>::verify(&sig.0, message, pubkey.as_ref())
171			}
172			fn public(&self) -> Self::Public {
173				Public(self.0.public())
174			}
175			fn to_raw_vec(&self) -> $crate::Vec<u8> {
176				self.0.to_raw_vec()
177			}
178		}
179
180		impl $crate::AppCrypto for Pair {
181			type Public = Public;
182			type Pair = Pair;
183			type Signature = Signature;
184			const ID: $crate::KeyTypeId = $key_type;
185			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
186		}
187
188		impl $crate::AppPair for Pair {
189			type Generic = $pair;
190		}
191
192		impl Pair {
193			/// Convert into wrapped generic key pair type.
194			pub fn into_inner(self) -> $pair {
195				self.0
196			}
197		}
198	};
199}
200
201/// Implements functions for the `Pair` trait when `feature = "std"` is enabled.
202#[doc(hidden)]
203#[cfg(feature = "std")]
204#[macro_export]
205macro_rules! app_crypto_pair_functions_if_std {
206	($pair:ty) => {
207		fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed) {
208			let r = <$pair>::generate_with_phrase(password);
209			(Self(r.0), r.1, r.2)
210		}
211	};
212}
213
214#[doc(hidden)]
215#[cfg(not(feature = "std"))]
216#[macro_export]
217macro_rules! app_crypto_pair_functions_if_std {
218	($pair:ty) => {};
219}
220
221/// Implements functions for the `Pair` trait when `feature = "full_crypto"` is enabled.
222#[doc(hidden)]
223#[cfg(feature = "full_crypto")]
224#[macro_export]
225macro_rules! app_crypto_pair_functions_if_full_crypto {
226	($pair:ty) => {
227		fn sign(&self, msg: &[u8]) -> Self::Signature {
228			Signature(self.0.sign(msg))
229		}
230	};
231}
232
233#[doc(hidden)]
234#[cfg(not(feature = "full_crypto"))]
235#[macro_export]
236macro_rules! app_crypto_pair_functions_if_full_crypto {
237	($pair:ty) => {};
238}
239
240/// Declares `Public` type which is functionally equivalent to `$public` but is
241/// new application-specific type whose identifier is `$key_type`.
242/// For full functionality, `app_crypto_public_common!` must be called too.
243/// Can only be used with `full_crypto` feature.
244#[doc(hidden)]
245#[macro_export]
246macro_rules! app_crypto_public_full_crypto {
247	($public:ty, $key_type:expr, $crypto_type:expr) => {
248		$crate::wrap! {
249			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
250			#[derive(
251				Clone, Eq, Hash, PartialEq, PartialOrd, Ord,
252				$crate::codec::Encode,
253				$crate::codec::Decode,
254				$crate::RuntimeDebug,
255				$crate::codec::MaxEncodedLen,
256				$crate::scale_info::TypeInfo,
257			)]
258			#[codec(crate = $crate::codec)]
259			pub struct Public($public);
260		}
261
262		impl $crate::CryptoType for Public {
263			type Pair = Pair;
264		}
265
266		impl $crate::AppCrypto for Public {
267			type Public = Public;
268			type Pair = Pair;
269			type Signature = Signature;
270			const ID: $crate::KeyTypeId = $key_type;
271			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
272		}
273	};
274}
275
276/// Declares `Public` type which is functionally equivalent to `$public` but is
277/// new application-specific type whose identifier is `$key_type`.
278/// For full functionality, `app_crypto_public_common!` must be called too.
279/// Can only be used without `full_crypto` feature.
280#[doc(hidden)]
281#[macro_export]
282macro_rules! app_crypto_public_not_full_crypto {
283	($public:ty, $key_type:expr, $crypto_type:expr) => {
284		$crate::wrap! {
285			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
286			#[derive(
287				Clone, Eq, Hash, PartialEq, Ord, PartialOrd,
288				$crate::codec::Encode,
289				$crate::codec::Decode,
290				$crate::RuntimeDebug,
291				$crate::codec::MaxEncodedLen,
292				$crate::scale_info::TypeInfo,
293			)]
294			pub struct Public($public);
295		}
296
297		impl $crate::CryptoType for Public {
298			type Pair = Pair;
299		}
300
301		impl $crate::AppCrypto for Public {
302			type Public = Public;
303			type Pair = Pair;
304			type Signature = Signature;
305			const ID: $crate::KeyTypeId = $key_type;
306			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
307		}
308	};
309}
310
311/// Declares `Public` type which is functionally equivalent to `$public` but is
312/// new application-specific type whose identifier is `$key_type`.
313/// For full functionality, `app_crypto_public_(not)_full_crypto!` must be called too.
314#[doc(hidden)]
315#[macro_export]
316macro_rules! app_crypto_public_common {
317	($public:ty, $sig:ty, $key_type:expr, $crypto_type:expr) => {
318		$crate::app_crypto_public_common_if_serde!();
319
320		impl AsRef<[u8]> for Public {
321			fn as_ref(&self) -> &[u8] {
322				self.0.as_ref()
323			}
324		}
325
326		impl AsMut<[u8]> for Public {
327			fn as_mut(&mut self) -> &mut [u8] {
328				self.0.as_mut()
329			}
330		}
331
332		impl $crate::ByteArray for Public {
333			const LEN: usize = <$public>::LEN;
334		}
335
336		impl $crate::Public for Public {}
337
338		impl $crate::AppPublic for Public {
339			type Generic = $public;
340		}
341
342		impl<'a> TryFrom<&'a [u8]> for Public {
343			type Error = ();
344
345			fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
346				<$public>::try_from(data).map(Into::into)
347			}
348		}
349
350		impl Public {
351			/// Convert into wrapped generic public key type.
352			pub fn into_inner(self) -> $public {
353				self.0
354			}
355		}
356	};
357}
358
359#[doc(hidden)]
360pub mod module_format_string_prelude {
361	#[cfg(all(not(feature = "std"), feature = "serde"))]
362	pub use alloc::{format, string::String};
363	#[cfg(feature = "std")]
364	pub use std::{format, string::String};
365}
366
367/// Implements traits for the public key type if `feature = "serde"` is enabled.
368#[cfg(feature = "serde")]
369#[doc(hidden)]
370#[macro_export]
371macro_rules! app_crypto_public_common_if_serde {
372	() => {
373		impl $crate::Derive for Public {
374			fn derive<Iter: Iterator<Item = $crate::DeriveJunction>>(
375				&self,
376				path: Iter,
377			) -> Option<Self> {
378				self.0.derive(path).map(Self)
379			}
380		}
381
382		impl core::fmt::Display for Public {
383			fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
384				use $crate::Ss58Codec;
385				write!(f, "{}", self.0.to_ss58check())
386			}
387		}
388
389		impl $crate::serde::Serialize for Public {
390			fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
391			where
392				S: $crate::serde::Serializer,
393			{
394				use $crate::Ss58Codec;
395				serializer.serialize_str(&self.to_ss58check())
396			}
397		}
398
399		impl<'de> $crate::serde::Deserialize<'de> for Public {
400			fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
401			where
402				D: $crate::serde::Deserializer<'de>,
403			{
404				use $crate::{module_format_string_prelude::*, Ss58Codec};
405
406				Public::from_ss58check(&String::deserialize(deserializer)?)
407					.map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e)))
408			}
409		}
410	};
411}
412
413#[cfg(not(feature = "serde"))]
414#[doc(hidden)]
415#[macro_export]
416macro_rules! app_crypto_public_common_if_serde {
417	() => {
418		impl $crate::Derive for Public {}
419	};
420}
421
422/// Declares Signature type which is functionally equivalent to `$sig`, but is new
423/// Application-specific type whose identifier is `$key_type`.
424/// For full functionality, app_crypto_public_common! must be called too.
425/// Can only be used with `full_crypto` feature
426#[doc(hidden)]
427#[macro_export]
428macro_rules! app_crypto_signature_full_crypto {
429	($sig:ty, $key_type:expr, $crypto_type:expr) => {
430		$crate::wrap! {
431			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
432			#[derive(Clone, Eq, PartialEq,
433				$crate::codec::Encode,
434				$crate::codec::Decode,
435				$crate::RuntimeDebug,
436				$crate::scale_info::TypeInfo,
437			)]
438			#[derive(Hash)]
439			pub struct Signature($sig);
440		}
441
442		impl $crate::CryptoType for Signature {
443			type Pair = Pair;
444		}
445
446		impl $crate::AppCrypto for Signature {
447			type Public = Public;
448			type Pair = Pair;
449			type Signature = Signature;
450			const ID: $crate::KeyTypeId = $key_type;
451			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
452		}
453	};
454}
455
456/// Declares `Signature` type which is functionally equivalent to `$sig`, but is new
457/// application-specific type whose identifier is `$key_type`.
458/// For full functionality, `app_crypto_signature_common` must be called too.
459/// Can only be used without `full_crypto` feature.
460#[doc(hidden)]
461#[macro_export]
462macro_rules! app_crypto_signature_not_full_crypto {
463	($sig:ty, $key_type:expr, $crypto_type:expr) => {
464		$crate::wrap! {
465			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
466			#[derive(Clone, Eq, PartialEq,
467				$crate::codec::Encode,
468				$crate::codec::Decode,
469				$crate::RuntimeDebug,
470				$crate::scale_info::TypeInfo,
471			)]
472			pub struct Signature($sig);
473		}
474
475		impl $crate::CryptoType for Signature {
476			type Pair = Pair;
477		}
478
479		impl $crate::AppCrypto for Signature {
480			type Public = Public;
481			type Pair = Pair;
482			type Signature = Signature;
483			const ID: $crate::KeyTypeId = $key_type;
484			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
485		}
486	};
487}
488
489/// Declares `Signature` type which is functionally equivalent to `$sig`, but is new
490/// application-specific type whose identifier is `$key_type`.
491/// For full functionality, app_crypto_signature_(not)_full_crypto! must be called too.
492#[doc(hidden)]
493#[macro_export]
494macro_rules! app_crypto_signature_common {
495	($sig:ty, $key_type:expr) => {
496		impl $crate::Deref for Signature {
497			type Target = [u8];
498
499			fn deref(&self) -> &Self::Target {
500				self.0.as_ref()
501			}
502		}
503
504		impl AsRef<[u8]> for Signature {
505			fn as_ref(&self) -> &[u8] {
506				self.0.as_ref()
507			}
508		}
509
510		impl AsMut<[u8]> for Signature {
511			fn as_mut(&mut self) -> &mut [u8] {
512				self.0.as_mut()
513			}
514		}
515
516		impl $crate::AppSignature for Signature {
517			type Generic = $sig;
518		}
519
520		impl<'a> TryFrom<&'a [u8]> for Signature {
521			type Error = ();
522
523			fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
524				<$sig>::try_from(data).map(Into::into)
525			}
526		}
527
528		impl TryFrom<$crate::Vec<u8>> for Signature {
529			type Error = ();
530
531			fn try_from(data: $crate::Vec<u8>) -> Result<Self, Self::Error> {
532				Self::try_from(&data[..])
533			}
534		}
535
536		impl $crate::Signature for Signature {}
537
538		impl $crate::ByteArray for Signature {
539			const LEN: usize = <$sig>::LEN;
540		}
541
542		impl Signature {
543			/// Convert into wrapped generic signature type.
544			pub fn into_inner(self) -> $sig {
545				self.0
546			}
547		}
548	};
549}
550
551/// Implement bidirectional `From` and on-way `AsRef`/`AsMut` for two types, `$inner` and `$outer`.
552///
553/// ```rust
554/// sp_application_crypto::wrap! {
555///     pub struct Wrapper(u32);
556/// }
557/// ```
558#[macro_export]
559macro_rules! wrap {
560	($( #[ $attr:meta ] )* struct $outer:ident($inner:ty);) => {
561		$( #[ $attr ] )*
562		struct $outer( $inner );
563		$crate::wrap!($inner, $outer);
564	};
565	($( #[ $attr:meta ] )* pub struct $outer:ident($inner:ty);) => {
566		$( #[ $attr ] )*
567		pub struct $outer( $inner );
568		$crate::wrap!($inner, $outer);
569	};
570	($inner:ty, $outer:ty) => {
571		impl $crate::Wraps for $outer {
572			type Inner = $inner;
573		}
574		impl From<$inner> for $outer {
575			fn from(inner: $inner) -> Self {
576				Self(inner)
577			}
578		}
579		impl From<$outer> for $inner {
580			fn from(outer: $outer) -> Self {
581				outer.0
582			}
583		}
584		impl AsRef<$inner> for $outer {
585			fn as_ref(&self) -> &$inner {
586				&self.0
587			}
588		}
589		impl AsMut<$inner> for $outer {
590			fn as_mut(&mut self) -> &mut $inner {
591				&mut self.0
592			}
593		}
594	}
595}
596
597/// Generate the given code if the pair type is available.
598///
599/// The pair type is available when `feature = "std"` || `feature = "full_crypto"`.
600///
601/// # Example
602///
603/// ```
604/// sp_application_crypto::with_pair! {
605///     pub type Pair = ();
606/// }
607/// ```
608#[macro_export]
609#[cfg(any(feature = "std", feature = "full_crypto"))]
610macro_rules! with_pair {
611	( $( $def:tt )* ) => {
612		$( $def )*
613	}
614}
615
616#[doc(hidden)]
617#[macro_export]
618#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))]
619macro_rules! with_pair {
620	( $( $def:tt )* ) => {};
621}