dpp/identity/v0/conversion/
json.rs1use crate::identity::conversion::json::IdentityJsonConversionMethodsV0;
2use crate::identity::conversion::platform_value::IdentityPlatformValueConversionMethodsV0;
3use crate::identity::{identity_public_key, IdentityV0, IDENTIFIER_FIELDS_RAW_OBJECT};
4use crate::ProtocolError;
5use platform_value::{ReplacementType, Value};
6use serde_json::Value as JsonValue;
7use std::convert::TryInto;
8
9impl IdentityJsonConversionMethodsV0 for IdentityV0 {
10 fn to_json_object(&self) -> Result<JsonValue, ProtocolError> {
11 self.to_cleaned_object()?
12 .try_into_validating_json()
13 .map_err(ProtocolError::ValueError)
14 }
15
16 fn to_json(&self) -> Result<JsonValue, ProtocolError> {
17 self.to_cleaned_object()?
18 .try_into()
19 .map_err(ProtocolError::ValueError)
20 }
21
22 fn from_json(json_object: JsonValue) -> Result<Self, ProtocolError> {
24 let mut platform_value: Value = json_object.into();
25
26 platform_value
27 .replace_at_paths(IDENTIFIER_FIELDS_RAW_OBJECT, ReplacementType::Identifier)?;
28
29 if let Some(public_keys_array) = platform_value.get_optional_array_mut_ref("publicKeys")? {
30 for public_key in public_keys_array.iter_mut() {
31 public_key.replace_at_paths(
32 identity_public_key::BINARY_DATA_FIELDS,
33 ReplacementType::BinaryBytes,
34 )?;
35 }
36 }
37
38 let identity: Self = platform_value::from_value(platform_value)?;
39
40 Ok(identity)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
48 use crate::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel};
49 use platform_value::{BinaryData, Identifier};
50 use std::collections::BTreeMap;
51
52 fn sample_identity_v0() -> IdentityV0 {
53 let mut keys: BTreeMap<u32, IdentityPublicKey> = BTreeMap::new();
54 keys.insert(
55 0,
56 IdentityPublicKey::V0(IdentityPublicKeyV0 {
57 id: 0,
58 purpose: Purpose::AUTHENTICATION,
59 security_level: SecurityLevel::MASTER,
60 contract_bounds: None,
61 key_type: KeyType::ECDSA_SECP256K1,
62 read_only: false,
63 data: BinaryData::new(vec![0x33; 33]),
64 disabled_at: None,
65 }),
66 );
67 IdentityV0 {
68 id: Identifier::from([9u8; 32]),
69 public_keys: keys,
70 balance: 42,
71 revision: 1,
72 }
73 }
74
75 #[test]
76 fn to_json_contains_expected_top_level_fields() {
77 let id = sample_identity_v0();
78 let json = id.to_json().expect("to_json");
79 let obj = json.as_object().expect("object");
80 assert!(obj.contains_key("id"));
81 assert!(obj.contains_key("publicKeys"));
82 assert!(obj.contains_key("balance"));
83 assert!(obj.contains_key("revision"));
84 }
85
86 #[test]
96 fn to_json_then_from_json_fails_binary_data_roundtrip_v0_frozen() {
97 let id = sample_identity_v0();
98 let json = id.to_json().unwrap();
99 let back = IdentityV0::from_json(json);
100 assert!(
101 back.is_err(),
102 "V0 to_json -> from_json roundtrip is not expected to succeed; \
103 if this starts to pass, V0 consensus behavior may have changed"
104 );
105 }
106
107 #[test]
108 fn to_json_object_encodes_identifier_as_bytes_array() {
109 let id = sample_identity_v0();
112 let json = id.to_json_object().expect("to_json_object");
113 let obj = json.as_object().expect("object");
114 let id_field =
115 obj.get("id").expect("id").as_array().expect(
116 "to_json_object should render the identifier as a JSON array of byte values",
117 );
118 assert_eq!(id_field.len(), 32);
119 }
120
121 #[test]
122 fn from_json_fails_on_garbage_input() {
123 let json = serde_json::json!({ "id": "not-a-valid-identifier" });
124 let result = IdentityV0::from_json(json);
125 assert!(result.is_err());
126 }
127
128 #[test]
135 fn from_json_fixture_fails_missing_format_version_v0_frozen() {
136 use crate::tests::fixtures::identity_fixture_json;
137 let json = identity_fixture_json();
138 let result = IdentityV0::from_json(json);
139 match result {
140 Err(e) => {
141 let msg = format!("{:?}", e);
142 assert!(
143 msg.contains("$formatVersion") || msg.contains("formatVersion"),
144 "expected missing-formatVersion error, got {msg}"
145 );
146 }
147 Ok(_) => panic!("expected from_json on legacy fixture to fail"),
148 }
149 }
150
151 #[test]
152 fn from_json_errors_when_public_keys_field_is_not_array() {
153 let json = serde_json::json!({
155 "id": "3bufpwQjL5qsvuP4fmCKgXJrKG852DDMYfi9J6XKqPAT",
156 "publicKeys": "oops",
157 "balance": 0,
158 "revision": 0,
159 });
160 let result = IdentityV0::from_json(json);
161 assert!(result.is_err());
162 }
163}