blueprint_crypto_sp_core/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "bls")]
4mod bls;
5#[cfg(feature = "bls")]
6pub use bls::*;
7
8#[cfg(feature = "aggregation")]
9mod aggregation;
10
11pub mod error;
12
13#[cfg(test)]
14mod tests;
15
16use blueprint_crypto_core::BytesEncoding;
17use blueprint_std::{string::String, vec::Vec};
18use sp_core::{ByteArray, Pair};
19
20macro_rules! impl_sp_core_pair_public {
24 ($key_type:ident, $pair_type:ty, $public:ty) => {
25 paste::paste! {
26 #[derive(Clone)]
31 pub struct [<Sp $key_type Pair>](pub $pair_type);
32
33 impl PartialEq for [<Sp $key_type Pair>] {
34 fn eq(&self, other: &Self) -> bool {
35 self.to_bytes() == other.to_bytes()
36 }
37 }
38
39 impl Eq for [<Sp $key_type Pair>] {}
40
41 impl PartialOrd for [<Sp $key_type Pair>] {
42 fn partial_cmp(&self, other: &Self) -> Option<blueprint_std::cmp::Ordering> {
43 Some(self.cmp(other))
44 }
45 }
46
47 impl Ord for [<Sp $key_type Pair>] {
48 fn cmp(&self, other: &Self) -> blueprint_std::cmp::Ordering {
49 self.to_bytes().cmp(&other.to_bytes())
50 }
51 }
52
53 impl blueprint_std::fmt::Debug for [<Sp $key_type Pair>] {
54 fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
55 write!(f, "{:?}", self.to_bytes())
56 }
57 }
58
59 impl serde::Serialize for [<Sp $key_type Pair>] {
60 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
61 where
62 S: serde::Serializer,
63 {
64 <Vec::<u8>>::serialize(&self.to_bytes(), serializer)
65 }
66 }
67
68 impl<'de> serde::Deserialize<'de> for [<Sp $key_type Pair>] {
69 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
70 where
71 D: serde::Deserializer<'de>,
72 {
73 let seed = <Vec::<u8>>::deserialize(deserializer)?;
74 let pair = <$pair_type>::from_seed_slice(&seed).map_err(|_| serde::de::Error::custom("Invalid seed length"))?;
75 Ok([<Sp $key_type Pair>](pair))
76 }
77 }
78
79 #[derive(Clone, serde::Serialize, serde::Deserialize)]
81 pub struct [<Sp $key_type Public>](pub <$pair_type as sp_core::Pair>::Public);
82
83 impl blueprint_std::hash::Hash for [<Sp $key_type Public>] {
84 fn hash<H: blueprint_std::hash::Hasher>(&self, state: &mut H) {
85 self.0.to_raw_vec().hash(state);
86 }
87 }
88
89 impl BytesEncoding for [<Sp $key_type Public>] {
90 fn to_bytes(&self) -> Vec<u8> {
91 self.0.to_raw_vec()
92 }
93
94 fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, serde::de::value::Error> {
95 Self::from_bytes_impl(bytes)
96 }
97 }
98
99 impl PartialEq for [<Sp $key_type Public>]{
100 fn eq(&self, other: &Self) -> bool {
101 self.0 == other.0
102 }
103 }
104
105 impl Eq for [<Sp $key_type Public>]{}
106
107 impl PartialOrd for [<Sp $key_type Public>]{
108 fn partial_cmp(&self, other: &Self) -> Option<blueprint_std::cmp::Ordering> {
109 Some(self.cmp(other))
110 }
111 }
112
113 impl Ord for [<Sp $key_type Public>]{
114 fn cmp(&self, other: &Self) -> blueprint_std::cmp::Ordering {
115 self.to_bytes().cmp(&other.to_bytes())
116 }
117 }
118
119 impl blueprint_std::fmt::Debug for [<Sp $key_type Public>]{
120 fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
121 write!(f, "{:?}", self.to_bytes())
122 }
123 }
124
125 impl blueprint_std::fmt::Display for [<Sp $key_type Public>] {
126 fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
127 write!(f, "{}", hex::encode(self.to_bytes()))
128 }
129 }
130 }
131 };
132}
133
134macro_rules! impl_sp_core_signature {
136 ($key_type:ident, $pair_type:ty) => {
137 paste::paste! {
138 #[derive(Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
139 pub struct [<Sp $key_type Signature>](pub <$pair_type as sp_core::Pair>::Signature);
140
141 impl PartialOrd for [<Sp $key_type Signature>] {
142 fn partial_cmp(&self, other: &Self) -> Option<blueprint_std::cmp::Ordering> {
143 Some(self.cmp(other))
144 }
145 }
146
147 impl Ord for [<Sp $key_type Signature>] {
148 fn cmp(&self, other: &Self) -> blueprint_std::cmp::Ordering {
149 self.0.0.cmp(&other.0.0)
150 }
151 }
152
153 impl blueprint_std::fmt::Debug for [<Sp $key_type Signature>] {
154 fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
155 write!(f, "{:?}", self.0.0)
156 }
157 }
158
159 impl blueprint_std::fmt::Display for [<Sp $key_type Signature>] {
160 fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
161 write!(f, "{}", hex::encode(self.0.0))
162 }
163 }
164
165 impl BytesEncoding for [<Sp $key_type Signature>] {
166 fn to_bytes(&self) -> Vec<u8> {
167 self.0.to_raw_vec()
168 }
169
170 fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, serde::de::value::Error> {
171 match <$pair_type as sp_core::Pair>::Signature::from_slice(bytes) {
172 Ok(sig) => Ok([<Sp $key_type Signature>](sig)),
173 Err(_) => Err(serde::de::Error::custom("Invalid signature length")),
174 }
175 }
176 }
177 }
178 };
179}
180
181macro_rules! impl_sp_core_key_type {
183 ($key_type:ident, $pair_type:ty) => {
184 paste::paste! {
185 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
186 pub struct [<Sp $key_type>];
187
188 impl blueprint_crypto_core::KeyType for [<Sp $key_type>] {
189 type Public = [<Sp $key_type Public>];
190 type Secret = [<Sp $key_type Pair>];
191 type Signature = [<Sp $key_type Signature>];
192 type Error = $crate::error::SpCoreError;
193
194 fn key_type_id() -> blueprint_crypto_core::KeyTypeId {
195 blueprint_crypto_core::KeyTypeId::$key_type
196 }
197
198 fn generate_with_seed(seed: Option<&[u8]>) -> $crate::error::Result<Self::Secret> {
199 match seed {
200 Some(seed) => {
201 if seed.len() != 32 {
202 return Err($crate::error::SpCoreError::InvalidSeed("Invalid seed length".into()));
203 }
204 let seed_array: [u8; 32] = seed.try_into()
205 .map_err(|_| $crate::error::SpCoreError::InvalidSeed("Invalid seed length".into()))?;
206 let pair = <$pair_type>::from_seed(&seed_array);
207 Ok([<Sp $key_type Pair>](pair))
208 }
209 None => {
210 #[cfg(feature = "std")]
211 let (pair, _) = <$pair_type>::generate();
212 #[cfg(not(feature = "std"))]
213 let pair = {
214 use blueprint_std::Rng;
215 let seed = Self::get_test_rng().r#gen::<[u8; 32]>();
216 <$pair_type>::from_seed(&seed)
217 };
218 Ok([<Sp $key_type Pair>](pair))
219 }
220 }
221 }
222
223 fn generate_with_string(secret: String) -> $crate::error::Result<Self::Secret> {
224 let seed = hex::decode(&secret)
226 .map_err(|_| $crate::error::SpCoreError::InvalidSeed("Invalid hex string".into()))?;
227 if seed.len() != 32 {
228 return Err($crate::error::SpCoreError::InvalidSeed("Invalid seed length".into()));
229 }
230 let seed_array: [u8; 32] = seed.try_into()
231 .map_err(|_| $crate::error::SpCoreError::InvalidSeed("Invalid seed length".into()))?;
232 let pair = <$pair_type>::from_seed(&seed_array);
233 Ok([<Sp $key_type Pair>](pair))
234 }
235
236 fn public_from_secret(secret: &Self::Secret) -> Self::Public {
237 [<Sp $key_type Public>](secret.0.public())
238 }
239
240 fn sign_with_secret(
241 secret: &mut Self::Secret,
242 msg: &[u8],
243 ) -> $crate::error::Result<Self::Signature> {
244 Ok([<Sp $key_type Signature>](secret.0.sign(msg)))
245 }
246
247 fn sign_with_secret_pre_hashed(
248 secret: &mut Self::Secret,
249 msg: &[u8; 32],
250 ) -> $crate::error::Result<Self::Signature> {
251 Ok([<Sp $key_type Signature>](secret.0.sign(msg)))
252 }
253
254 fn verify(public: &Self::Public, msg: &[u8], signature: &Self::Signature) -> bool {
255 <$pair_type as sp_core::Pair>::verify(&signature.0, msg, &public.0)
256 }
257 }
258
259 impl [<Sp $key_type Pair>] {
260 pub fn public(&self) -> [<Sp $key_type Public>] {
261 [<Sp $key_type Public>](self.0.public())
262 }
263 }
264
265 impl BytesEncoding for [<Sp $key_type Pair>] {
266 fn to_bytes(&self) -> Vec<u8> {
267 self.0.to_raw_vec()
268 }
269
270 fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, serde::de::value::Error> {
271 let inner = <$pair_type>::from_seed_slice(bytes).map_err(|_| serde::de::Error::custom("Invalid seed length"))?;
272 Ok(Self(inner))
273 }
274 }
275
276 impl blueprint_std::ops::Deref for [<Sp $key_type Pair>] {
277 type Target = $pair_type;
278
279 fn deref(&self) -> &Self::Target {
280 &self.0
281 }
282 }
283
284 impl blueprint_std::ops::DerefMut for [<Sp $key_type Pair>] {
285 fn deref_mut(&mut self) -> &mut Self::Target {
286 &mut self.0
287 }
288 }
289 }
290 };
291}
292
293macro_rules! impl_sp_core_crypto {
295 ($key_type:ident, $module:ident) => {
296 impl_sp_core_pair_public!($key_type, sp_core::$module::Pair, sp_core::$module::Public);
297 impl_sp_core_signature!($key_type, sp_core::$module::Pair);
298 impl_sp_core_key_type!($key_type, sp_core::$module::Pair);
299 };
300}
301
302impl_sp_core_crypto!(Ecdsa, ecdsa);
303
304impl SpEcdsaPublic {
305 fn from_bytes_impl(bytes: &[u8]) -> Result<Self, serde::de::value::Error> {
306 let inner = <sp_core::ecdsa::Pair as sp_core::Pair>::Public::from_full(bytes)
307 .map_err(|_| serde::de::Error::custom("Invalid public key length"))?;
308 Ok(Self(inner))
309 }
310}
311
312impl_sp_core_crypto!(Ed25519, ed25519);
313
314impl SpEd25519Public {
315 fn from_bytes_impl(bytes: &[u8]) -> Result<Self, serde::de::value::Error> {
316 let inner = <sp_core::ed25519::Pair as sp_core::Pair>::Public::from_slice(bytes)
317 .map_err(|_| serde::de::Error::custom("Invalid public key length"))?;
318 Ok(Self(inner))
319 }
320}
321
322impl_sp_core_crypto!(Sr25519, sr25519);
323
324impl SpSr25519Public {
325 fn from_bytes_impl(bytes: &[u8]) -> Result<Self, serde::de::value::Error> {
326 let inner = <sp_core::sr25519::Pair as sp_core::Pair>::Public::from_slice(bytes)
327 .map_err(|_| serde::de::Error::custom("Invalid public key length"))?;
328 Ok(Self(inner))
329 }
330}
331
332impl Copy for SpEcdsaPublic {}
333impl Copy for SpEd25519Public {}
334impl Copy for SpSr25519Public {}