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
63pub trait PlatformDeserializable {
64    fn deserialize_from_bytes(data: &[u8]) -> Result<Self, ProtocolError>
65    where
66        Self: Sized,
67    {
68        Self::deserialize_from_bytes_no_limit(data)
69    }
70
71    fn deserialize_from_bytes_no_limit(data: &[u8]) -> Result<Self, ProtocolError>
72    where
73        Self: Sized;
74}
75
76pub trait PlatformDeserializableFromVersionedStructure {
77    /// We will deserialize a versioned structure into a code structure
78    /// For example we have DataContractV0 and DataContractV1
79    /// The system version will tell which version to deserialize into
80    /// This happens by first deserializing the data into a potentially versioned structure
81    /// For example we could have DataContractSerializationFormatV0 and DataContractSerializationFormatV1
82    /// Both of the structures will be valid in perpetuity as they are saved into the state.
83    /// So from the bytes we could get DataContractSerializationFormatV0.
84    /// Then the system_version given will tell to transform DataContractSerializationFormatV0 into
85    /// DataContractV1 (if system version is 1)
86    fn versioned_deserialize(
87        data: &[u8],
88        platform_version: &PlatformVersion,
89    ) -> Result<Self, ProtocolError>
90    where
91        Self: Sized;
92}
93
94pub trait PlatformDeserializableWithPotentialValidationFromVersionedStructure {
95    /// We will deserialize a versioned structure into a code structure
96    /// For example we have DataContractV0 and DataContractV1
97    /// The system version will tell which version to deserialize into
98    /// This happens by first deserializing the data into a potentially versioned structure
99    /// For example we could have DataContractSerializationFormatV0 and DataContractSerializationFormatV1
100    /// Both of the structures will be valid in perpetuity as they are saved into the state.
101    /// So from the bytes we could get DataContractSerializationFormatV0.
102    /// Then the system_version given will tell to transform DataContractSerializationFormatV0 into
103    /// DataContractV1 (if system version is 1)
104    fn versioned_deserialize(
105        data: &[u8],
106        full_validation: bool,
107        platform_version: &PlatformVersion,
108    ) -> Result<Self, ProtocolError>
109    where
110        Self: Sized;
111}
112
113pub trait PlatformDeserializableWithBytesLenFromVersionedStructure {
114    /// We will deserialize a versioned structure into a code structure
115    /// For example we have DataContractV0 and DataContractV1
116    /// The system version will tell which version to deserialize into
117    /// This happens by first deserializing the data into a potentially versioned structure
118    /// For example we could have DataContractSerializationFormatV0 and DataContractSerializationFormatV1
119    /// Both of the structures will be valid in perpetuity as they are saved into the state.
120    /// So from the bytes we could get DataContractSerializationFormatV0.
121    /// Then the system_version given will tell to transform DataContractSerializationFormatV0 into
122    /// DataContractV1 (if system version is 1)
123    fn versioned_deserialize_with_bytes_len(
124        data: &[u8],
125        full_validation: bool,
126        platform_version: &PlatformVersion,
127    ) -> Result<(Self, usize), ProtocolError>
128    where
129        Self: Sized;
130}
131
132pub trait PlatformLimitDeserializableFromVersionedStructure {
133    fn versioned_limit_deserialize(
134        data: &[u8],
135        platform_version: &PlatformVersion,
136    ) -> Result<Self, ProtocolError>
137    where
138        Self: Sized;
139}
140
141#[cfg(feature = "value-conversion")]
142pub trait ValueConvertible: Serialize + DeserializeOwned {
143    fn to_object(&self) -> Result<Value, ProtocolError>
144    where
145        Self: Sized,
146    {
147        platform_value::to_value(self).map_err(ProtocolError::ValueError)
148    }
149
150    fn into_object(self) -> Result<Value, ProtocolError>
151    where
152        Self: Sized,
153    {
154        platform_value::to_value(self).map_err(ProtocolError::ValueError)
155    }
156
157    fn from_object(value: Value) -> Result<Self, ProtocolError>
158    where
159        Self: Sized,
160    {
161        platform_value::from_value(value).map_err(ProtocolError::ValueError)
162    }
163
164    fn from_object_ref(value: &Value) -> Result<Self, ProtocolError>
165    where
166        Self: Sized,
167    {
168        platform_value::from_value(value.clone()).map_err(ProtocolError::ValueError)
169    }
170}
171
172/// Convert to/from JSON using human-readable serde (Identifier=base58, Bytes=base64).
173///
174/// This trait produces clean `serde_json::Value` with native number types.
175/// Any JS-boundary concerns (large number stringification) are handled by the WASM layer.
176#[cfg(feature = "json-conversion")]
177pub trait JsonConvertible: Serialize + DeserializeOwned {
178    fn to_json(&self) -> Result<JsonValue, ProtocolError> {
179        serde_json::to_value(self).map_err(|e| ProtocolError::EncodingError(e.to_string()))
180    }
181
182    fn from_json(json: JsonValue) -> Result<Self, ProtocolError> {
183        serde_json::from_value(json).map_err(|e| ProtocolError::DecodingError(e.to_string()))
184    }
185}
186
187pub trait PlatformMessageSignable {
188    #[cfg(feature = "message-signature-verification")]
189    fn verify_signature(
190        &self,
191        public_key_type: KeyType,
192        public_key_data: &[u8],
193        signature: &[u8],
194    ) -> SimpleConsensusValidationResult;
195
196    #[cfg(feature = "message-signing")]
197    fn sign_by_private_key(
198        &self,
199        private_key: &[u8],
200        key_type: KeyType,
201        bls: &impl BlsModule,
202    ) -> Result<Vec<u8>, ProtocolError>;
203}