dpp/serialization/serialization_traits.rs
1#[cfg(any(
2 feature = "message-signature-verification",
3 feature = "message-signing"
4))]
5use crate::identity::KeyType;
6
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9#[cfg(feature = "json-conversion")]
10use serde_json::Value as JsonValue;
11
12#[cfg(feature = "message-signature-verification")]
13use crate::validation::SimpleConsensusValidationResult;
14use crate::version::PlatformVersion;
15#[cfg(feature = "message-signing")]
16use crate::BlsModule;
17use crate::ProtocolError;
18use platform_value::Value;
19
20pub trait Signable {
21 fn signable_bytes(&self) -> Result<Vec<u8>, ProtocolError>;
22}
23
24pub trait PlatformSerializable {
25 type Error;
26 fn serialize_to_bytes(&self) -> Result<Vec<u8>, Self::Error>;
27
28 /// If the trait is not used just do a simple serialize
29 fn serialize_consume_to_bytes(self) -> Result<Vec<u8>, Self::Error>
30 where
31 Self: Sized,
32 {
33 self.serialize_to_bytes()
34 }
35}
36
37pub trait PlatformSerializableWithPlatformVersion {
38 type Error;
39 /// Version based serialization is done based on the desired structure version.
40 /// For example we have DataContractV0 and DataContractV1 for code based Contracts
41 /// This means objects that will execute code
42 /// And we would have DataContractSerializationFormatV0 and DataContractSerializationFormatV1
43 /// which are the different ways to serialize the concept of a data contract.
44 /// The data contract would call versioned_serialize. There should be a converted for each
45 /// Data contract Version towards each DataContractSerializationFormat
46 fn serialize_to_bytes_with_platform_version(
47 &self,
48 platform_version: &PlatformVersion,
49 ) -> Result<Vec<u8>, Self::Error>;
50
51 /// If the trait is not used just do a simple serialize
52 fn serialize_consume_to_bytes_with_platform_version(
53 self,
54 platform_version: &PlatformVersion,
55 ) -> Result<Vec<u8>, Self::Error>
56 where
57 Self: Sized,
58 {
59 self.serialize_to_bytes_with_platform_version(platform_version)
60 }
61}
62
63/// Deserialization of bytes this node wrote itself: Drive state read back
64/// from GroveDB, wallet storage, locally generated fixtures.
65///
66/// Runs bincode's ordinary decoder, which reserves each collection from its
67/// length prefix, so it must never see bytes that arrived from a peer, a
68/// client, a proof or a host caller; those go through
69/// [`PlatformDeserializableUntrusted`].
70///
71/// The derive implements the two `_with_bytes_len` methods, which report how
72/// many bytes the value took; the other methods are defaults over them.
73pub trait PlatformDeserializableTrusted {
74 /// Decodes under the type's configured byte budget, returning the value
75 /// and the number of bytes it took.
76 fn deserialize_from_bytes_trusted_with_bytes_len(
77 data: &[u8],
78 ) -> Result<(Self, usize), ProtocolError>
79 where
80 Self: Sized;
81
82 /// [`Self::deserialize_from_bytes_trusted_with_bytes_len`] without the
83 /// byte budget.
84 fn deserialize_from_bytes_trusted_no_limit_with_bytes_len(
85 data: &[u8],
86 ) -> Result<(Self, usize), ProtocolError>
87 where
88 Self: Sized;
89
90 /// Decodes under the type's configured byte budget. Bytes left over after
91 /// the value are ignored; [`Self::deserialize_from_bytes_trusted_exact`]
92 /// refuses them.
93 fn deserialize_from_bytes_trusted(data: &[u8]) -> Result<Self, ProtocolError>
94 where
95 Self: Sized,
96 {
97 Self::deserialize_from_bytes_trusted_with_bytes_len(data).map(|(value, _)| value)
98 }
99
100 fn deserialize_from_bytes_trusted_no_limit(data: &[u8]) -> Result<Self, ProtocolError>
101 where
102 Self: Sized,
103 {
104 Self::deserialize_from_bytes_trusted_no_limit_with_bytes_len(data).map(|(value, _)| value)
105 }
106
107 /// [`Self::deserialize_from_bytes_trusted`] that also refuses bytes left
108 /// over after the value.
109 fn deserialize_from_bytes_trusted_exact(data: &[u8]) -> Result<Self, ProtocolError>
110 where
111 Self: Sized,
112 {
113 let (value, consumed) = Self::deserialize_from_bytes_trusted_with_bytes_len(data)?;
114 refuse_left_over_bytes::<Self>(data.len(), consumed)?;
115 Ok(value)
116 }
117}
118
119/// Deserialization of bytes from outside this node: state transitions, query
120/// requests and cursors, proofs, SDK responses, host-supplied input.
121///
122/// Runs bincode's untrusted decoder, which reserves nothing from a length
123/// prefix before the elements it announces have actually been read, so a
124/// short input claiming a huge collection fails instead of allocating.
125///
126/// The derive implements the two `_with_bytes_len` methods, which report how
127/// many bytes the value took; the other methods are defaults over them.
128pub trait PlatformDeserializableUntrusted {
129 /// Decodes under the type's configured byte budget, returning the value
130 /// and the number of bytes it took.
131 fn deserialize_from_bytes_untrusted_with_bytes_len(
132 data: &[u8],
133 ) -> Result<(Self, usize), ProtocolError>
134 where
135 Self: Sized;
136
137 /// [`Self::deserialize_from_bytes_untrusted_with_bytes_len`] without the
138 /// byte budget.
139 fn deserialize_from_bytes_untrusted_no_limit_with_bytes_len(
140 data: &[u8],
141 ) -> Result<(Self, usize), ProtocolError>
142 where
143 Self: Sized;
144
145 /// Decodes under the type's configured byte budget. Bytes left over after
146 /// the value are ignored; [`Self::deserialize_from_bytes_untrusted_exact`]
147 /// refuses them.
148 fn deserialize_from_bytes_untrusted(data: &[u8]) -> Result<Self, ProtocolError>
149 where
150 Self: Sized,
151 {
152 Self::deserialize_from_bytes_untrusted_with_bytes_len(data).map(|(value, _)| value)
153 }
154
155 fn deserialize_from_bytes_untrusted_no_limit(data: &[u8]) -> Result<Self, ProtocolError>
156 where
157 Self: Sized,
158 {
159 Self::deserialize_from_bytes_untrusted_no_limit_with_bytes_len(data).map(|(value, _)| value)
160 }
161
162 /// [`Self::deserialize_from_bytes_untrusted`] that also refuses bytes left
163 /// over after the value.
164 ///
165 /// A value followed by anything decodes loosely as the value alone, so a
166 /// caller that shows a user what the bytes contain and then signs them
167 /// must use this one to know the value is all there is.
168 fn deserialize_from_bytes_untrusted_exact(data: &[u8]) -> Result<Self, ProtocolError>
169 where
170 Self: Sized,
171 {
172 let (value, consumed) = Self::deserialize_from_bytes_untrusted_with_bytes_len(data)?;
173 refuse_left_over_bytes::<Self>(data.len(), consumed)?;
174 Ok(value)
175 }
176}
177
178/// The error for a decode of `T` that took `consumed` of `len` input bytes.
179fn refuse_left_over_bytes<T>(len: usize, consumed: usize) -> Result<(), ProtocolError> {
180 if consumed == len {
181 return Ok(());
182 }
183 Err(ProtocolError::PlatformDeserializationError(format!(
184 "unable to deserialize {}: {} bytes left over after the value",
185 std::any::type_name::<T>(),
186 len.saturating_sub(consumed)
187 )))
188}
189
190/// We will deserialize a versioned structure into a code structure
191/// For example we have DataContractV0 and DataContractV1
192/// The system version will tell which version to deserialize into
193/// This happens by first deserializing the data into a potentially versioned structure
194/// For example we could have DataContractSerializationFormatV0 and DataContractSerializationFormatV1
195/// Both of the structures will be valid in perpetuity as they are saved into the state.
196/// So from the bytes we could get DataContractSerializationFormatV0.
197/// Then the system_version given will tell to transform DataContractSerializationFormatV0 into
198/// DataContractV1 (if system version is 1)
199///
200/// Trusted twin: bytes this node wrote itself, see [`PlatformDeserializableTrusted`].
201pub trait PlatformDeserializableFromVersionedStructureTrusted {
202 fn versioned_deserialize_trusted(
203 data: &[u8],
204 platform_version: &PlatformVersion,
205 ) -> Result<Self, ProtocolError>
206 where
207 Self: Sized;
208}
209
210/// Untrusted twin of [`PlatformDeserializableFromVersionedStructureTrusted`]:
211/// bytes from outside this node, see [`PlatformDeserializableUntrusted`].
212pub trait PlatformDeserializableFromVersionedStructureUntrusted {
213 fn versioned_deserialize_untrusted(
214 data: &[u8],
215 platform_version: &PlatformVersion,
216 ) -> Result<Self, ProtocolError>
217 where
218 Self: Sized;
219}
220
221/// Versioned deserialization with optional full validation of the decoded
222/// structure (see [`PlatformDeserializableFromVersionedStructureTrusted`] for
223/// how versioned structures decode).
224///
225/// Trusted twin: bytes this node wrote itself, see [`PlatformDeserializableTrusted`].
226pub trait PlatformDeserializableWithPotentialValidationFromVersionedStructureTrusted {
227 fn versioned_deserialize_trusted(
228 data: &[u8],
229 full_validation: bool,
230 platform_version: &PlatformVersion,
231 ) -> Result<Self, ProtocolError>
232 where
233 Self: Sized;
234}
235
236/// Untrusted twin of
237/// [`PlatformDeserializableWithPotentialValidationFromVersionedStructureTrusted`]:
238/// bytes from outside this node, see [`PlatformDeserializableUntrusted`].
239pub trait PlatformDeserializableWithPotentialValidationFromVersionedStructureUntrusted {
240 fn versioned_deserialize_untrusted(
241 data: &[u8],
242 full_validation: bool,
243 platform_version: &PlatformVersion,
244 ) -> Result<Self, ProtocolError>
245 where
246 Self: Sized;
247}
248
249/// Versioned deserialization that also reports how many bytes were consumed
250/// (see [`PlatformDeserializableFromVersionedStructureTrusted`] for how
251/// versioned structures decode).
252///
253/// Trusted twin: bytes this node wrote itself, see [`PlatformDeserializableTrusted`].
254pub trait PlatformDeserializableWithBytesLenFromVersionedStructureTrusted {
255 fn versioned_deserialize_with_bytes_len_trusted(
256 data: &[u8],
257 full_validation: bool,
258 platform_version: &PlatformVersion,
259 ) -> Result<(Self, usize), ProtocolError>
260 where
261 Self: Sized;
262}
263
264/// Untrusted twin of
265/// [`PlatformDeserializableWithBytesLenFromVersionedStructureTrusted`]:
266/// bytes from outside this node, see [`PlatformDeserializableUntrusted`].
267pub trait PlatformDeserializableWithBytesLenFromVersionedStructureUntrusted {
268 fn versioned_deserialize_with_bytes_len_untrusted(
269 data: &[u8],
270 full_validation: bool,
271 platform_version: &PlatformVersion,
272 ) -> Result<(Self, usize), ProtocolError>
273 where
274 Self: Sized;
275}
276
277/// Versioned deserialization under the type's configured byte limit.
278///
279/// Trusted twin: bytes this node wrote itself, see [`PlatformDeserializableTrusted`].
280pub trait PlatformLimitDeserializableFromVersionedStructureTrusted {
281 fn versioned_limit_deserialize_trusted(
282 data: &[u8],
283 platform_version: &PlatformVersion,
284 ) -> Result<Self, ProtocolError>
285 where
286 Self: Sized;
287}
288
289/// Untrusted twin of [`PlatformLimitDeserializableFromVersionedStructureTrusted`]:
290/// bytes from outside this node, see [`PlatformDeserializableUntrusted`].
291pub trait PlatformLimitDeserializableFromVersionedStructureUntrusted {
292 fn versioned_limit_deserialize_untrusted(
293 data: &[u8],
294 platform_version: &PlatformVersion,
295 ) -> Result<Self, ProtocolError>
296 where
297 Self: Sized;
298}
299
300pub trait ValueConvertible: Serialize + DeserializeOwned {
301 fn to_object(&self) -> Result<Value, ProtocolError>
302 where
303 Self: Sized,
304 {
305 platform_value::to_value(self).map_err(ProtocolError::ValueError)
306 }
307
308 fn into_object(self) -> Result<Value, ProtocolError>
309 where
310 Self: Sized,
311 {
312 platform_value::to_value(self).map_err(ProtocolError::ValueError)
313 }
314
315 fn from_object(value: Value) -> Result<Self, ProtocolError>
316 where
317 Self: Sized,
318 {
319 platform_value::from_value(value).map_err(ProtocolError::ValueError)
320 }
321
322 fn from_object_ref(value: &Value) -> Result<Self, ProtocolError>
323 where
324 Self: Sized,
325 {
326 platform_value::from_value(value.clone()).map_err(ProtocolError::ValueError)
327 }
328}
329
330/// Convert to/from JSON using **human-readable** serde (`Identifier` = base58,
331/// binary = base64).
332///
333/// This trait produces clean `serde_json::Value` with native number types.
334/// Any JS-boundary concerns (large number stringification) are handled by the
335/// WASM layer.
336///
337/// # ⚠️ HR / non-HR divergence (Critical-1)
338///
339/// `JsonConvertible` calls `serde_json::to_value`, which uses a serializer
340/// that reports `is_human_readable() == true`. The mirror trait
341/// [`ValueConvertible`] uses `platform_value::to_value`, which reports
342/// `false`. Types whose `Serialize` impl branches on `is_human_readable()`
343/// produce **structurally different output** between the two paths:
344///
345/// | Type | `to_json()` (HR) | `to_object()` (non-HR) |
346/// |---|---|---|
347/// | [`platform_value::Identifier`] | `"5bV6jUfh..."` (bs58 string) | `Value::Identifier([u8; 32])` |
348/// | [`platform_value::BinaryData`] | `"sg=="` (base64 string) | `Value::Bytes(Vec<u8>)` |
349/// | `Bytes20` / `Bytes32` / `Bytes36` | base64 string | `Value::Bytes32([u8; N])` etc. |
350/// | `CoreScript` | `"dqkU..."` (base64 string) | `Value::Bytes(Vec<u8>)` |
351///
352/// **Do not assume** `self.to_object()?.try_into_json()` ≡ `self.to_json()`.
353/// They render the same field as a string in one and a byte array in the
354/// other. Round-trip tests should exercise each path independently.
355///
356/// # ⚠️ `ContentDeserializer` caveat
357///
358/// Manual `Deserialize` impls that branch on `deserializer.is_human_readable()`
359/// must also handle `serde::__private::de::ContentDeserializer`, used
360/// internally by `#[serde(tag = "...")]` enums. ContentDeserializer **always
361/// reports `is_human_readable: true`** regardless of the original source — so
362/// a non-HR `platform_value::Value` flowing into a tagged enum gets shape-
363/// inferred as if it were HR. Recipe: write a dual-shape visitor accepting
364/// both shapes in the HR branch via `deserialize_any`. See
365/// [`platform_value::Bytes32::deserialize`] for the canonical example, and
366/// `rs-dpp/src/serialization/serde_bytes.rs` for `[u8; N]` / `Vec<u8>`.
367#[cfg(feature = "json-conversion")]
368pub trait JsonConvertible: Serialize + DeserializeOwned {
369 fn to_json(&self) -> Result<JsonValue, ProtocolError> {
370 serde_json::to_value(self).map_err(|e| ProtocolError::EncodingError(e.to_string()))
371 }
372
373 fn from_json(json: JsonValue) -> Result<Self, ProtocolError> {
374 serde_json::from_value(json).map_err(|e| ProtocolError::DecodingError(e.to_string()))
375 }
376}
377
378pub trait PlatformMessageSignable {
379 #[cfg(feature = "message-signature-verification")]
380 fn verify_signature(
381 &self,
382 public_key_type: KeyType,
383 public_key_data: &[u8],
384 signature: &[u8],
385 ) -> SimpleConsensusValidationResult;
386
387 #[cfg(feature = "message-signing")]
388 fn sign_by_private_key(
389 &self,
390 private_key: &[u8],
391 key_type: KeyType,
392 bls: &impl BlsModule,
393 ) -> Result<Vec<u8>, ProtocolError>;
394}