1#![allow(clippy::from_over_into)]
2
3use crate::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
4use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
5#[cfg(feature = "value-conversion")]
6use crate::serialization::ValueConvertible;
7use bincode::{Decode, Encode};
8use derive_more::From;
9use serde::{Deserialize, Serialize};
10
11mod key_type;
12mod purpose;
13mod security_level;
14pub use key_type::KeyType;
15pub use purpose::Purpose;
16pub use security_level::SecurityLevel;
17pub mod accessors;
18pub mod conversion;
19pub mod fields;
20pub mod v0;
21use crate::version::PlatformVersion;
22use crate::ProtocolError;
23pub use fields::*;
24use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
25
26pub mod methods;
27pub use methods::*;
28pub mod contract_bounds;
29#[cfg(feature = "random-public-keys")]
30mod random;
31
32pub type KeyID = u32;
33pub type KeyCount = KeyID;
34pub type TimestampMillis = u64;
35
36#[derive(
37 Debug,
38 Clone,
39 Eq,
40 PartialEq,
41 Serialize,
42 Deserialize,
43 Encode,
44 Decode,
45 PlatformDeserialize,
46 PlatformSerialize,
47 From,
48 Hash,
49 Ord,
50 PartialOrd,
51)]
52#[platform_serialize(limit = 2000, unversioned)] #[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
54#[serde(tag = "$formatVersion")]
55pub enum IdentityPublicKey {
56 #[serde(rename = "0")]
57 V0(IdentityPublicKeyV0),
58}
59
60impl IdentityPublicKey {
61 pub fn is_master(&self) -> bool {
63 self.security_level() == SecurityLevel::MASTER
64 }
65
66 pub fn max_possible_size_key(
81 id: KeyID,
82 platform_version: &PlatformVersion,
83 ) -> Result<Self, ProtocolError> {
84 match platform_version
85 .dpp
86 .identity_versions
87 .identity_key_structure_version
88 {
89 0 => Ok(IdentityPublicKeyV0::max_possible_size_key(id).into()),
90 version => Err(ProtocolError::UnknownVersionMismatch {
91 method: "IdentityPublicKey::max_possible_size_key".to_string(),
92 known_versions: vec![0],
93 received: version,
94 }),
95 }
96 }
97
98 pub fn default_versioned(platform_version: &PlatformVersion) -> Result<Self, ProtocolError> {
99 match platform_version
100 .dpp
101 .identity_versions
102 .identity_key_structure_version
103 {
104 0 => Ok(IdentityPublicKeyV0::default().into()),
105 version => Err(ProtocolError::UnknownVersionMismatch {
106 method: "IdentityPublicKey::default_versioned".to_string(),
107 known_versions: vec![0],
108 received: version,
109 }),
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use crate::identity::identity_public_key::accessors::v0::{
117 IdentityPublicKeyGettersV0, IdentityPublicKeySettersV0,
118 };
119 use crate::identity::identity_public_key::contract_bounds::ContractBounds;
120 use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
121 use crate::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel};
122 use crate::serialization::{PlatformDeserializable, PlatformSerializable};
123 use platform_value::{BinaryData, Identifier};
124 use platform_version::version::LATEST_PLATFORM_VERSION;
125 use rand::SeedableRng;
126
127 #[test]
128 fn test_identity_key_serialization_deserialization() {
129 let mut rng = rand::rngs::StdRng::from_entropy();
130 let key: IdentityPublicKey =
131 IdentityPublicKeyV0::random_ecdsa_master_authentication_key_with_rng(
132 1,
133 &mut rng,
134 LATEST_PLATFORM_VERSION,
135 )
136 .expect("expected a random key")
137 .0
138 .into();
139 let serialized = key.serialize_to_bytes().expect("expected to serialize key");
140 let unserialized: IdentityPublicKey =
141 PlatformDeserializable::deserialize_from_bytes(serialized.as_slice())
142 .expect("expected to deserialize key");
143 assert_eq!(key, unserialized)
144 }
145
146 fn make_key_v0(security_level: SecurityLevel) -> IdentityPublicKey {
149 IdentityPublicKey::V0(IdentityPublicKeyV0 {
150 id: 42,
151 purpose: Purpose::AUTHENTICATION,
152 security_level,
153 contract_bounds: None,
154 key_type: KeyType::ECDSA_SECP256K1,
155 data: BinaryData::new(vec![0u8; 33]),
156 read_only: false,
157 disabled_at: None,
158 })
159 }
160
161 #[test]
162 fn test_is_master_true_when_security_level_master() {
163 let key = make_key_v0(SecurityLevel::MASTER);
164 assert!(key.is_master());
165 }
166
167 #[test]
168 fn test_is_master_false_for_other_levels() {
169 assert!(!make_key_v0(SecurityLevel::CRITICAL).is_master());
170 assert!(!make_key_v0(SecurityLevel::HIGH).is_master());
171 assert!(!make_key_v0(SecurityLevel::MEDIUM).is_master());
172 }
173
174 #[test]
177 fn test_max_possible_size_key_v0_returns_bls_sized_data() {
178 let key = IdentityPublicKey::max_possible_size_key(123, LATEST_PLATFORM_VERSION)
180 .expect("max_possible_size_key should work for v0");
181 assert_eq!(key.id(), 123);
182 assert_eq!(key.purpose(), Purpose::AUTHENTICATION);
183 assert_eq!(key.security_level(), SecurityLevel::MASTER);
184 assert!(!key.read_only());
185 assert!(key.contract_bounds().is_none());
186 assert!(key.disabled_at().is_none());
187 assert_eq!(key.data().len(), key.key_type().default_size());
189 assert!(key.data().as_slice().iter().all(|b| *b == 0xff));
190 }
191
192 #[test]
195 fn test_default_versioned_returns_v0_default() {
196 let key = IdentityPublicKey::default_versioned(LATEST_PLATFORM_VERSION)
197 .expect("default_versioned should work for v0");
198 assert_eq!(key.id(), 0);
200 assert_eq!(key.purpose(), Purpose::default());
201 assert_eq!(key.security_level(), SecurityLevel::default());
202 assert_eq!(key.key_type(), KeyType::default());
203 }
204
205 #[test]
208 fn test_wrapper_getters_delegate_to_v0() {
209 let inner = IdentityPublicKeyV0 {
210 id: 7,
211 purpose: Purpose::TRANSFER,
212 security_level: SecurityLevel::CRITICAL,
213 contract_bounds: Some(ContractBounds::SingleContract {
214 id: Identifier::from([0x01u8; 32]),
215 }),
216 key_type: KeyType::BLS12_381,
217 data: BinaryData::new(vec![2u8; 48]),
218 read_only: true,
219 disabled_at: Some(1_700_000_000_000),
220 };
221 let key = IdentityPublicKey::V0(inner.clone());
222 assert_eq!(key.id(), 7);
223 assert_eq!(key.purpose(), Purpose::TRANSFER);
224 assert_eq!(key.security_level(), SecurityLevel::CRITICAL);
225 assert_eq!(key.key_type(), KeyType::BLS12_381);
226 assert!(key.read_only());
227 assert_eq!(key.data().as_slice(), &vec![2u8; 48][..]);
228 assert_eq!(key.disabled_at(), Some(1_700_000_000_000));
229 assert!(key.is_disabled());
230 assert!(key.contract_bounds().is_some());
231
232 let cloned = key.clone();
234 assert_eq!(cloned.data_owned().as_slice(), &vec![2u8; 48][..]);
235 }
236
237 #[test]
238 fn test_wrapper_setters_delegate_to_v0() {
239 let mut key = make_key_v0(SecurityLevel::HIGH);
240 key.set_id(99);
241 key.set_purpose(Purpose::ENCRYPTION);
242 key.set_security_level(SecurityLevel::CRITICAL);
243 key.set_key_type(KeyType::BLS12_381);
244 key.set_read_only(true);
245 key.set_data(BinaryData::new(vec![0xABu8; 48]));
246 key.set_disabled_at(1234);
247
248 assert_eq!(key.id(), 99);
249 assert_eq!(key.purpose(), Purpose::ENCRYPTION);
250 assert_eq!(key.security_level(), SecurityLevel::CRITICAL);
251 assert_eq!(key.key_type(), KeyType::BLS12_381);
252 assert!(key.read_only());
253 assert_eq!(key.data().as_slice(), &vec![0xABu8; 48][..]);
254 assert_eq!(key.disabled_at(), Some(1234));
255 assert!(key.is_disabled());
256
257 key.remove_disabled_at();
258 assert_eq!(key.disabled_at(), None);
259 assert!(!key.is_disabled());
260 }
261
262 #[test]
264 fn test_from_v0_into_wrapper() {
265 let v0 = IdentityPublicKeyV0 {
266 id: 5,
267 purpose: Purpose::VOTING,
268 security_level: SecurityLevel::MEDIUM,
269 contract_bounds: None,
270 key_type: KeyType::ECDSA_HASH160,
271 data: BinaryData::new(vec![0u8; 20]),
272 read_only: false,
273 disabled_at: None,
274 };
275 let wrapped: IdentityPublicKey = v0.clone().into();
276 assert_eq!(wrapped.id(), 5);
277 assert_eq!(wrapped.purpose(), Purpose::VOTING);
278 assert_eq!(wrapped.security_level(), SecurityLevel::MEDIUM);
279 assert_eq!(wrapped, IdentityPublicKey::V0(v0));
281 }
282
283 #[test]
285 fn test_v0_default_fields() {
286 let v0 = IdentityPublicKeyV0::default();
287 assert_eq!(v0.id, 0);
288 assert_eq!(v0.purpose, Purpose::default());
289 assert_eq!(v0.security_level, SecurityLevel::default());
290 assert_eq!(v0.key_type, KeyType::default());
291 assert!(!v0.read_only);
292 assert_eq!(v0.data.as_slice().len(), 0);
293 assert!(v0.disabled_at.is_none());
294 assert!(v0.contract_bounds.is_none());
295 }
296
297 #[test]
299 fn test_keys_are_orderable_and_cloneable() {
300 let a = IdentityPublicKey::V0(IdentityPublicKeyV0 {
301 id: 1,
302 ..Default::default()
303 });
304 let b = IdentityPublicKey::V0(IdentityPublicKeyV0 {
305 id: 2,
306 ..Default::default()
307 });
308 assert!(a < b);
309 let a_clone = a.clone();
310 assert_eq!(a, a_clone);
311 }
312}
313
314#[cfg(all(test, feature = "random-public-keys"))]
315mod random_tests {
316 use crate::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
317 use crate::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel};
318 use platform_version::version::LATEST_PLATFORM_VERSION;
319
320 #[test]
323 fn test_random_key_with_seed_is_deterministic() {
324 let k1 = IdentityPublicKey::random_key(1, Some(42), LATEST_PLATFORM_VERSION);
325 let k2 = IdentityPublicKey::random_key(1, Some(42), LATEST_PLATFORM_VERSION);
326 assert_eq!(k1, k2);
327 }
328
329 #[test]
330 fn test_random_keys_returns_requested_count() {
331 let keys = IdentityPublicKey::random_keys(0, 5, Some(7), LATEST_PLATFORM_VERSION);
332 assert_eq!(keys.len(), 5);
333 let mut ids: Vec<_> = keys.iter().map(|k| k.id()).collect();
335 ids.sort();
336 assert_eq!(ids, vec![0, 1, 2, 3, 4]);
337 }
338
339 #[test]
340 fn test_random_authentication_key_is_always_authentication_purpose() {
341 for id in 0..5u32 {
342 let k = IdentityPublicKey::random_authentication_key(
343 id,
344 Some(id as u64),
345 LATEST_PLATFORM_VERSION,
346 );
347 assert_eq!(k.purpose(), Purpose::AUTHENTICATION);
348 }
349 }
350
351 #[test]
352 fn test_random_authentication_keys_returns_requested_count_and_all_auth() {
353 let keys =
354 IdentityPublicKey::random_authentication_keys(0, 3, Some(11), LATEST_PLATFORM_VERSION);
355 assert_eq!(keys.len(), 3);
356 for k in &keys {
357 assert_eq!(k.purpose(), Purpose::AUTHENTICATION);
358 }
359 }
360
361 #[test]
362 fn test_random_ecdsa_master_authentication_key_has_expected_attributes() {
363 let (key, _priv) = IdentityPublicKey::random_ecdsa_master_authentication_key(
364 0,
365 Some(1),
366 LATEST_PLATFORM_VERSION,
367 )
368 .expect("expected master authentication key");
369 assert_eq!(key.key_type(), KeyType::ECDSA_SECP256K1);
370 assert_eq!(key.purpose(), Purpose::AUTHENTICATION);
371 assert_eq!(key.security_level(), SecurityLevel::MASTER);
372 assert!(!key.read_only());
373 assert_eq!(key.data().len(), 33);
374 }
375
376 #[test]
377 fn test_random_ecdsa_critical_level_authentication_key_attributes() {
378 let (key, _priv) = IdentityPublicKey::random_ecdsa_critical_level_authentication_key(
379 1,
380 Some(2),
381 LATEST_PLATFORM_VERSION,
382 )
383 .expect("expected critical auth key");
384 assert_eq!(key.key_type(), KeyType::ECDSA_SECP256K1);
385 assert_eq!(key.purpose(), Purpose::AUTHENTICATION);
386 assert_eq!(key.security_level(), SecurityLevel::CRITICAL);
387 }
388
389 #[test]
390 fn test_random_ecdsa_high_level_authentication_key_attributes() {
391 let (key, _priv) = IdentityPublicKey::random_ecdsa_high_level_authentication_key(
392 2,
393 Some(3),
394 LATEST_PLATFORM_VERSION,
395 )
396 .expect("expected high-level auth key");
397 assert_eq!(key.key_type(), KeyType::ECDSA_SECP256K1);
398 assert_eq!(key.purpose(), Purpose::AUTHENTICATION);
399 assert_eq!(key.security_level(), SecurityLevel::HIGH);
400 }
401
402 #[test]
403 fn test_random_masternode_owner_key_has_owner_purpose_and_is_read_only() {
404 let (key, _priv) =
405 IdentityPublicKey::random_masternode_owner_key(3, Some(4), LATEST_PLATFORM_VERSION)
406 .expect("expected masternode owner key");
407 assert_eq!(key.key_type(), KeyType::ECDSA_HASH160);
408 assert_eq!(key.purpose(), Purpose::OWNER);
409 assert_eq!(key.security_level(), SecurityLevel::CRITICAL);
410 assert!(key.read_only());
411 }
412
413 #[test]
414 fn test_random_masternode_transfer_key_has_transfer_purpose_and_is_read_only() {
415 let (key, _priv) =
416 IdentityPublicKey::random_masternode_transfer_key(4, Some(5), LATEST_PLATFORM_VERSION)
417 .expect("expected masternode transfer key");
418 assert_eq!(key.key_type(), KeyType::ECDSA_HASH160);
419 assert_eq!(key.purpose(), Purpose::TRANSFER);
420 assert_eq!(key.security_level(), SecurityLevel::CRITICAL);
421 assert!(key.read_only());
422 }
423
424 #[test]
425 fn test_main_keys_with_random_authentication_keys_errors_when_count_below_two() {
426 use rand::{rngs::StdRng, SeedableRng};
427 let mut rng = StdRng::seed_from_u64(1);
428 let err =
429 IdentityPublicKey::main_keys_with_random_authentication_keys_with_private_keys_with_rng(
430 1,
431 &mut rng,
432 LATEST_PLATFORM_VERSION,
433 )
434 .unwrap_err();
435 match err {
436 crate::ProtocolError::PublicKeyGenerationError(msg) => {
437 assert!(msg.contains("at least 2"));
438 }
439 other => panic!("expected PublicKeyGenerationError, got {:?}", other),
440 }
441 }
442
443 #[test]
444 fn test_main_keys_with_random_authentication_keys_count_two() {
445 use rand::{rngs::StdRng, SeedableRng};
446 let mut rng = StdRng::seed_from_u64(2);
447 let keys = IdentityPublicKey::main_keys_with_random_authentication_keys_with_private_keys_with_rng(
448 2,
449 &mut rng,
450 LATEST_PLATFORM_VERSION,
451 )
452 .expect("expected keys");
453 assert_eq!(keys.len(), 2);
454 assert_eq!(keys[0].0.security_level(), SecurityLevel::MASTER);
456 assert_eq!(keys[0].0.key_type(), KeyType::ECDSA_SECP256K1);
457 assert_eq!(keys[1].0.security_level(), SecurityLevel::HIGH);
458 assert_eq!(keys[1].0.key_type(), KeyType::ECDSA_SECP256K1);
459 }
460
461 #[test]
462 fn test_main_keys_with_random_authentication_keys_count_three() {
463 use rand::{rngs::StdRng, SeedableRng};
464 let mut rng = StdRng::seed_from_u64(3);
465 let keys = IdentityPublicKey::main_keys_with_random_authentication_keys_with_private_keys_with_rng(
466 3,
467 &mut rng,
468 LATEST_PLATFORM_VERSION,
469 )
470 .expect("expected keys");
471 assert_eq!(keys.len(), 3);
472 assert_eq!(keys[0].0.security_level(), SecurityLevel::MASTER);
473 assert_eq!(keys[1].0.security_level(), SecurityLevel::CRITICAL);
474 assert_eq!(keys[2].0.security_level(), SecurityLevel::HIGH);
475 }
476
477 #[test]
478 fn test_random_unique_keys_with_rng_matches_count() {
479 use rand::{rngs::StdRng, SeedableRng};
480 let mut rng = StdRng::seed_from_u64(9);
481 let keys =
482 IdentityPublicKey::random_unique_keys_with_rng(4, &mut rng, LATEST_PLATFORM_VERSION)
483 .expect("expected keys");
484 assert_eq!(keys.len(), 4);
485 let ids: Vec<_> = keys.iter().map(|k| k.id()).collect();
487 assert_eq!(ids, vec![0, 1, 2, 3]);
488 }
489
490 #[test]
491 fn test_random_keys_with_rng_returns_requested_count() {
492 use rand::{rngs::StdRng, SeedableRng};
493 let mut rng = StdRng::seed_from_u64(10);
494 let keys = IdentityPublicKey::random_keys_with_rng(3, &mut rng, LATEST_PLATFORM_VERSION);
495 assert_eq!(keys.len(), 3);
496 }
497
498 #[test]
499 fn test_random_authentication_keys_with_private_keys_with_rng_returns_pairs() {
500 use rand::{rngs::StdRng, SeedableRng};
501 let mut rng = StdRng::seed_from_u64(11);
502 let pairs = IdentityPublicKey::random_authentication_keys_with_private_keys_with_rng(
503 5,
504 3,
505 &mut rng,
506 LATEST_PLATFORM_VERSION,
507 )
508 .expect("expected pairs");
509 assert_eq!(pairs.len(), 3);
510 let ids: Vec<_> = pairs.iter().map(|(k, _)| k.id()).collect();
511 assert_eq!(ids, vec![5, 6, 7]);
512 for (k, _) in &pairs {
513 assert_eq!(k.purpose(), Purpose::AUTHENTICATION);
514 }
515 }
516
517 #[test]
518 fn test_random_voting_key_with_rng_attributes() {
519 use rand::{rngs::StdRng, SeedableRng};
520 let mut rng = StdRng::seed_from_u64(13);
521 let (k, _priv) =
522 IdentityPublicKey::random_voting_key_with_rng(0, &mut rng, LATEST_PLATFORM_VERSION)
523 .expect("expected voting key");
524 assert_eq!(k.purpose(), Purpose::VOTING);
525 assert_eq!(k.key_type(), KeyType::ECDSA_HASH160);
526 assert_eq!(k.security_level(), SecurityLevel::MEDIUM);
527 }
528
529 #[test]
530 fn test_random_key_with_known_attributes_honors_inputs() {
531 use crate::identity::contract_bounds::ContractBounds;
532 use platform_value::Identifier;
533 use rand::{rngs::StdRng, SeedableRng};
534 let mut rng = StdRng::seed_from_u64(17);
535 let bounds = ContractBounds::SingleContract {
536 id: Identifier::from([0x77u8; 32]),
537 };
538 let (k, _priv) = IdentityPublicKey::random_key_with_known_attributes(
539 42,
540 &mut rng,
541 Purpose::TRANSFER,
542 SecurityLevel::CRITICAL,
543 KeyType::ECDSA_SECP256K1,
544 Some(bounds.clone()),
545 LATEST_PLATFORM_VERSION,
546 )
547 .expect("expected key");
548 assert_eq!(k.id(), 42);
549 assert_eq!(k.purpose(), Purpose::TRANSFER);
550 assert_eq!(k.security_level(), SecurityLevel::CRITICAL);
551 assert_eq!(k.key_type(), KeyType::ECDSA_SECP256K1);
552 assert_eq!(k.contract_bounds(), Some(&bounds));
553 }
554}