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::codec::DecodeWithMemTracking,
255				$crate::RuntimeDebug,
256				$crate::codec::MaxEncodedLen,
257				$crate::scale_info::TypeInfo,
258			)]
259			#[codec(crate = $crate::codec)]
260			pub struct Public($public);
261		}
262
263		impl $crate::CryptoType for Public {
264			type Pair = Pair;
265		}
266
267		impl $crate::AppCrypto for Public {
268			type Public = Public;
269			type Pair = Pair;
270			type Signature = Signature;
271			const ID: $crate::KeyTypeId = $key_type;
272			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
273		}
274	};
275}
276
277/// Declares `Public` type which is functionally equivalent to `$public` but is
278/// new application-specific type whose identifier is `$key_type`.
279/// For full functionality, `app_crypto_public_common!` must be called too.
280/// Can only be used without `full_crypto` feature.
281#[doc(hidden)]
282#[macro_export]
283macro_rules! app_crypto_public_not_full_crypto {
284	($public:ty, $key_type:expr, $crypto_type:expr) => {
285		$crate::wrap! {
286			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
287			#[derive(
288				Clone, Eq, Hash, PartialEq, Ord, PartialOrd,
289				$crate::codec::Encode,
290				$crate::codec::Decode,
291				$crate::codec::DecodeWithMemTracking,
292				$crate::RuntimeDebug,
293				$crate::codec::MaxEncodedLen,
294				$crate::scale_info::TypeInfo,
295			)]
296			pub struct Public($public);
297		}
298
299		impl $crate::CryptoType for Public {
300			type Pair = Pair;
301		}
302
303		impl $crate::AppCrypto for Public {
304			type Public = Public;
305			type Pair = Pair;
306			type Signature = Signature;
307			const ID: $crate::KeyTypeId = $key_type;
308			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
309		}
310	};
311}
312
313/// Declares `Public` type which is functionally equivalent to `$public` but is
314/// new application-specific type whose identifier is `$key_type`.
315/// For full functionality, `app_crypto_public_(not)_full_crypto!` must be called too.
316#[doc(hidden)]
317#[macro_export]
318macro_rules! app_crypto_public_common {
319	($public:ty, $sig:ty, $key_type:expr, $crypto_type:expr) => {
320		$crate::app_crypto_public_common_if_serde!();
321
322		impl AsRef<[u8]> for Public {
323			fn as_ref(&self) -> &[u8] {
324				self.0.as_ref()
325			}
326		}
327
328		impl AsMut<[u8]> for Public {
329			fn as_mut(&mut self) -> &mut [u8] {
330				self.0.as_mut()
331			}
332		}
333
334		impl $crate::ByteArray for Public {
335			const LEN: usize = <$public>::LEN;
336		}
337
338		impl $crate::Public for Public {}
339
340		impl $crate::AppPublic for Public {
341			type Generic = $public;
342		}
343
344		impl<'a> TryFrom<&'a [u8]> for Public {
345			type Error = ();
346
347			fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
348				<$public>::try_from(data).map(Into::into)
349			}
350		}
351
352		impl Public {
353			/// Convert into wrapped generic public key type.
354			pub fn into_inner(self) -> $public {
355				self.0
356			}
357		}
358	};
359}
360
361#[doc(hidden)]
362pub mod module_format_string_prelude {
363	#[cfg(all(not(feature = "std"), feature = "serde"))]
364	pub use alloc::{format, string::String};
365	#[cfg(feature = "std")]
366	pub use std::{format, string::String};
367}
368
369/// Implements traits for the public key type if `feature = "serde"` is enabled.
370#[cfg(feature = "serde")]
371#[doc(hidden)]
372#[macro_export]
373macro_rules! app_crypto_public_common_if_serde {
374	() => {
375		impl $crate::Derive for Public {
376			fn derive<Iter: Iterator<Item = $crate::DeriveJunction>>(
377				&self,
378				path: Iter,
379			) -> Option<Self> {
380				self.0.derive(path).map(Self)
381			}
382		}
383
384		impl core::fmt::Display for Public {
385			fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
386				use $crate::Ss58Codec;
387				write!(f, "{}", self.0.to_ss58check())
388			}
389		}
390
391		impl $crate::serde::Serialize for Public {
392			fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
393			where
394				S: $crate::serde::Serializer,
395			{
396				use $crate::Ss58Codec;
397				serializer.serialize_str(&self.to_ss58check())
398			}
399		}
400
401		impl<'de> $crate::serde::Deserialize<'de> for Public {
402			fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
403			where
404				D: $crate::serde::Deserializer<'de>,
405			{
406				use $crate::{module_format_string_prelude::*, Ss58Codec};
407
408				Public::from_ss58check(&String::deserialize(deserializer)?)
409					.map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e)))
410			}
411		}
412	};
413}
414
415#[cfg(not(feature = "serde"))]
416#[doc(hidden)]
417#[macro_export]
418macro_rules! app_crypto_public_common_if_serde {
419	() => {
420		impl $crate::Derive for Public {}
421	};
422}
423
424/// Declares Signature type which is functionally equivalent to `$sig`, but is new
425/// Application-specific type whose identifier is `$key_type`.
426/// For full functionality, app_crypto_public_common! must be called too.
427/// Can only be used with `full_crypto` feature
428#[doc(hidden)]
429#[macro_export]
430macro_rules! app_crypto_signature_full_crypto {
431	($sig:ty, $key_type:expr, $crypto_type:expr) => {
432		$crate::wrap! {
433			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
434			#[derive(Clone, Eq, PartialEq,
435				$crate::codec::Encode,
436				$crate::codec::Decode,
437				$crate::codec::DecodeWithMemTracking,
438				$crate::RuntimeDebug,
439				$crate::scale_info::TypeInfo,
440			)]
441			#[derive(Hash)]
442			pub struct Signature($sig);
443		}
444
445		impl $crate::CryptoType for Signature {
446			type Pair = Pair;
447		}
448
449		impl $crate::AppCrypto for Signature {
450			type Public = Public;
451			type Pair = Pair;
452			type Signature = Signature;
453			const ID: $crate::KeyTypeId = $key_type;
454			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
455		}
456	};
457}
458
459/// Declares `Signature` type which is functionally equivalent to `$sig`, but is new
460/// application-specific type whose identifier is `$key_type`.
461/// For full functionality, `app_crypto_signature_common` must be called too.
462/// Can only be used without `full_crypto` feature.
463#[doc(hidden)]
464#[macro_export]
465macro_rules! app_crypto_signature_not_full_crypto {
466	($sig:ty, $key_type:expr, $crypto_type:expr) => {
467		$crate::wrap! {
468			/// A generic `AppPublic` wrapper type over $public crypto; this has no specific App.
469			#[derive(Clone, Eq, PartialEq,
470				$crate::codec::Encode,
471				$crate::codec::Decode,
472				$crate::codec::DecodeWithMemTracking,
473				$crate::RuntimeDebug,
474				$crate::scale_info::TypeInfo,
475			)]
476			pub struct Signature($sig);
477		}
478
479		impl $crate::CryptoType for Signature {
480			type Pair = Pair;
481		}
482
483		impl $crate::AppCrypto for Signature {
484			type Public = Public;
485			type Pair = Pair;
486			type Signature = Signature;
487			const ID: $crate::KeyTypeId = $key_type;
488			const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type;
489		}
490	};
491}
492
493/// Declares `Signature` type which is functionally equivalent to `$sig`, but is new
494/// application-specific type whose identifier is `$key_type`.
495/// For full functionality, app_crypto_signature_(not)_full_crypto! must be called too.
496#[doc(hidden)]
497#[macro_export]
498macro_rules! app_crypto_signature_common {
499	($sig:ty, $key_type:expr) => {
500		impl $crate::Deref for Signature {
501			type Target = [u8];
502
503			fn deref(&self) -> &Self::Target {
504				self.0.as_ref()
505			}
506		}
507
508		impl AsRef<[u8]> for Signature {
509			fn as_ref(&self) -> &[u8] {
510				self.0.as_ref()
511			}
512		}
513
514		impl AsMut<[u8]> for Signature {
515			fn as_mut(&mut self) -> &mut [u8] {
516				self.0.as_mut()
517			}
518		}
519
520		impl $crate::AppSignature for Signature {
521			type Generic = $sig;
522		}
523
524		impl<'a> TryFrom<&'a [u8]> for Signature {
525			type Error = ();
526
527			fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
528				<$sig>::try_from(data).map(Into::into)
529			}
530		}
531
532		impl TryFrom<$crate::Vec<u8>> for Signature {
533			type Error = ();
534
535			fn try_from(data: $crate::Vec<u8>) -> Result<Self, Self::Error> {
536				Self::try_from(&data[..])
537			}
538		}
539
540		impl $crate::Signature for Signature {}
541
542		impl $crate::ByteArray for Signature {
543			const LEN: usize = <$sig>::LEN;
544		}
545
546		impl Signature {
547			/// Convert into wrapped generic signature type.
548			pub fn into_inner(self) -> $sig {
549				self.0
550			}
551		}
552	};
553}
554
555/// Implement bidirectional `From` and on-way `AsRef`/`AsMut` for two types, `$inner` and `$outer`.
556///
557/// ```rust
558/// sp_application_crypto::wrap! {
559///     pub struct Wrapper(u32);
560/// }
561/// ```
562#[macro_export]
563macro_rules! wrap {
564	($( #[ $attr:meta ] )* struct $outer:ident($inner:ty);) => {
565		$( #[ $attr ] )*
566		struct $outer( $inner );
567		$crate::wrap!($inner, $outer);
568	};
569	($( #[ $attr:meta ] )* pub struct $outer:ident($inner:ty);) => {
570		$( #[ $attr ] )*
571		pub struct $outer( $inner );
572		$crate::wrap!($inner, $outer);
573	};
574	($inner:ty, $outer:ty) => {
575		impl $crate::Wraps for $outer {
576			type Inner = $inner;
577		}
578		impl From<$inner> for $outer {
579			fn from(inner: $inner) -> Self {
580				Self(inner)
581			}
582		}
583		impl From<$outer> for $inner {
584			fn from(outer: $outer) -> Self {
585				outer.0
586			}
587		}
588		impl AsRef<$inner> for $outer {
589			fn as_ref(&self) -> &$inner {
590				&self.0
591			}
592		}
593		impl AsMut<$inner> for $outer {
594			fn as_mut(&mut self) -> &mut $inner {
595				&mut self.0
596			}
597		}
598	}
599}
600
601/// Generate the given code if the pair type is available.
602///
603/// The pair type is available when `feature = "std"` || `feature = "full_crypto"`.
604///
605/// # Example
606///
607/// ```
608/// sp_application_crypto::with_pair! {
609///     pub type Pair = ();
610/// }
611/// ```
612#[macro_export]
613#[cfg(any(feature = "std", feature = "full_crypto"))]
614macro_rules! with_pair {
615	( $( $def:tt )* ) => {
616		$( $def )*
617	}
618}
619
620#[doc(hidden)]
621#[macro_export]
622#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))]
623macro_rules! with_pair {
624	( $( $def:tt )* ) => {};
625}