Skip to main content

dpp/identity/v0/
mod.rs

1mod conversion;
2#[cfg(feature = "random-identities")]
3pub mod random;
4
5#[cfg(feature = "json-conversion")]
6use crate::serialization::json_safe_fields;
7#[cfg(feature = "json-conversion")]
8use crate::serialization::JsonConvertible;
9#[cfg(feature = "value-conversion")]
10use crate::serialization::ValueConvertible;
11use std::collections::BTreeMap;
12#[cfg(feature = "value-conversion")]
13use std::convert::TryFrom;
14use std::hash::{Hash, Hasher};
15
16use crate::identity::{IdentityPublicKey, KeyID, PartialIdentity};
17use crate::prelude::Revision;
18#[cfg(feature = "value-conversion")]
19use platform_value::Value;
20
21#[cfg(feature = "value-conversion")]
22use crate::errors::ProtocolError;
23use crate::identifier::Identifier;
24#[cfg(feature = "identity-serialization")]
25use bincode::{Decode, Encode};
26
27/// Implement the Identity. Identity is a low-level construct that provides the foundation
28/// for user-facing functionality on the platform
29#[cfg_attr(feature = "json-conversion", json_safe_fields)]
30#[derive(Default, Debug, Clone, Eq, PartialEq)]
31#[cfg_attr(feature = "identity-serialization", derive(Encode, Decode))]
32#[cfg_attr(
33    feature = "serde-conversion",
34    derive(serde::Serialize, serde::Deserialize),
35    serde(rename_all = "camelCase")
36)]
37#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
38pub struct IdentityV0 {
39    pub id: Identifier,
40    #[cfg_attr(feature = "serde-conversion", serde(with = "public_key_serialization"))]
41    pub public_keys: BTreeMap<KeyID, IdentityPublicKey>,
42    pub balance: u64,
43    pub revision: Revision,
44}
45
46impl Hash for IdentityV0 {
47    fn hash<H: Hasher>(&self, state: &mut H) {
48        self.id.hash(state);
49    }
50}
51
52#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
53impl JsonConvertible for IdentityV0 {}
54
55mod public_key_serialization {
56    use crate::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
57    use crate::identity::{IdentityPublicKey, KeyID};
58    use serde::ser::SerializeSeq;
59    use serde::{Deserialize, Serializer};
60    use std::collections::BTreeMap;
61
62    /// deserialize_public_keys deserializes public keys from a vector
63    pub fn deserialize<'de, D>(
64        deserializer: D,
65    ) -> Result<BTreeMap<KeyID, IdentityPublicKey>, D::Error>
66    where
67        D: serde::Deserializer<'de>,
68    {
69        let public_key_vec: Vec<IdentityPublicKey> = Deserialize::deserialize(deserializer)?;
70        Ok(public_key_vec.into_iter().map(|k| (k.id(), k)).collect())
71    }
72
73    pub fn serialize<S>(
74        public_keys: &BTreeMap<KeyID, IdentityPublicKey>,
75        serializer: S,
76    ) -> Result<S::Ok, S::Error>
77    where
78        S: Serializer,
79    {
80        let mut seq = serializer.serialize_seq(Some(public_keys.len()))?;
81        for element in public_keys.values() {
82            seq.serialize_element(element)?;
83        }
84        seq.end()
85    }
86}
87
88impl IdentityV0 {
89    /// Get Identity protocol version
90    pub fn get_feature_version(&self) -> u16 {
91        0
92    }
93
94    /// Convenience method to get Partial Identity Info
95    pub fn into_partial_identity_info(self) -> PartialIdentity {
96        let Self {
97            id,
98            public_keys,
99            balance,
100            revision,
101            ..
102        } = self;
103        PartialIdentity {
104            id,
105            loaded_public_keys: public_keys,
106            balance: Some(balance),
107            revision: Some(revision),
108            not_found_public_keys: Default::default(),
109        }
110    }
111
112    /// Convenience method to get Partial Identity Info
113    pub fn into_partial_identity_info_no_balance(self) -> PartialIdentity {
114        let Self {
115            id,
116            public_keys,
117            revision,
118            ..
119        } = self;
120        PartialIdentity {
121            id,
122            loaded_public_keys: public_keys,
123            balance: None,
124            revision: Some(revision),
125            not_found_public_keys: Default::default(),
126        }
127    }
128}
129
130#[cfg(feature = "value-conversion")]
131impl TryFrom<Value> for IdentityV0 {
132    type Error = ProtocolError;
133
134    fn try_from(value: Value) -> Result<Self, Self::Error> {
135        platform_value::from_value(value).map_err(ProtocolError::ValueError)
136    }
137}
138
139#[cfg(feature = "value-conversion")]
140impl TryFrom<&Value> for IdentityV0 {
141    type Error = ProtocolError;
142
143    fn try_from(value: &Value) -> Result<Self, Self::Error> {
144        platform_value::from_value(value.clone()).map_err(ProtocolError::ValueError)
145    }
146}
147
148#[cfg(all(
149    test,
150    feature = "json-conversion",
151    feature = "value-conversion",
152    feature = "serde-conversion"
153))]
154mod json_convertible_tests_identityv0 {
155    use super::*;
156
157    #[test]
158    fn json_round_trip_identityv0() {
159        use crate::serialization::JsonConvertible;
160        let original = IdentityV0::default();
161        let json = original.to_json().expect("to_json");
162        let recovered = IdentityV0::from_json(json).expect("from_json");
163        assert_eq!(original, recovered);
164    }
165
166    #[test]
167    fn value_round_trip_identityv0() {
168        use crate::serialization::ValueConvertible;
169        let original = IdentityV0::default();
170        let value = original.to_object().expect("to_object");
171        let recovered = IdentityV0::from_object(value).expect("from_object");
172        assert_eq!(original, recovered);
173    }
174}