referrerpolicy=no-referrer-when-downgrade

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