snarkvm_ledger_narwhal_data/
lib.rs1use console::prelude::*;
17
18use ::bytes::Bytes;
19
20#[cfg(feature = "async")]
21use tokio::task;
22
23const PREFIX: &str = "data";
24
25const MAX_DATA_SIZE: u32 = 1024 * 1024 * 1024; #[derive(Clone, PartialEq, Eq)]
33pub enum Data<T: FromBytes + ToBytes + Send + 'static> {
34 Object(T),
35 Buffer(Bytes),
36}
37
38impl<T: FromBytes + ToBytes + Send + 'static> Data<T> {
39 pub fn to_checksum<N: Network>(&self) -> Result<N::TransmissionChecksum> {
40 let preimage = match self {
42 Self::Object(object) => object.to_bytes_le()?.to_bits_le(),
43 Self::Buffer(bytes) => bytes.deref().to_bits_le(),
44 };
45 let hash = N::hash_sha3_256(&preimage)?;
47 let num_bits = usize::try_from(N::TransmissionChecksum::BITS).map_err(error)?;
49 N::TransmissionChecksum::from_bits_le(&hash[0..num_bits])
51 }
52
53 pub fn into<T2: From<Data<T>> + From<T> + FromBytes + ToBytes + Send + 'static>(self) -> Data<T2> {
54 match self {
55 Self::Object(x) => Data::Object(x.into()),
56 Self::Buffer(bytes) => Data::Buffer(bytes),
57 }
58 }
59
60 #[cfg(feature = "async")]
61 pub async fn deserialize(self) -> Result<T> {
62 match self {
63 Self::Object(x) => Ok(x),
64 Self::Buffer(bytes) => match task::spawn_blocking(move || T::from_bytes_le(&bytes)).await {
65 Ok(x) => x,
66 Err(err) => Err(err.into()),
67 },
68 }
69 }
70
71 pub fn deserialize_blocking(self) -> Result<T> {
72 match self {
73 Self::Object(x) => Ok(x),
74 Self::Buffer(bytes) => T::from_bytes_le(&bytes),
75 }
76 }
77
78 #[cfg(feature = "async")]
79 pub async fn serialize(self) -> Result<Bytes> {
80 match self {
81 Self::Object(x) => match task::spawn_blocking(move || x.to_bytes_le()).await {
82 Ok(bytes) => bytes.map(|vec| vec.into()),
83 Err(err) => Err(err.into()),
84 },
85 Self::Buffer(bytes) => Ok(bytes),
86 }
87 }
88
89 pub fn serialize_blocking_into<W: Write>(&self, writer: &mut W) -> Result<()> {
90 match self {
91 Self::Object(x) => Ok(x.write_le(writer)?),
92 Self::Buffer(bytes) => Ok(writer.write_all(bytes)?),
93 }
94 }
95}
96
97impl<T: FromBytes + ToBytes + DeserializeOwned + Send + 'static> FromStr for Data<T> {
98 type Err = Error;
99
100 fn from_str(data: &str) -> Result<Self, Self::Err> {
102 Ok(serde_json::from_str(data)?)
103 }
104}
105
106impl<T: FromBytes + ToBytes + Serialize + Send + 'static> Debug for Data<T> {
107 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
109 Display::fmt(self, f)
110 }
111}
112
113impl<T: FromBytes + ToBytes + Serialize + Send + 'static> Display for Data<T> {
114 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
116 write!(f, "{}", serde_json::to_string(self).map_err::<fmt::Error, _>(ser::Error::custom)?)
117 }
118}
119
120impl<T: FromBytes + ToBytes + Send + 'static> FromBytes for Data<T> {
121 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
123 let version = u8::read_le(&mut reader)?;
125 if version != 1 {
127 return Err(error("Invalid data version"));
128 }
129
130 let num_bytes = u32::read_le(&mut reader)?;
132 if num_bytes > MAX_DATA_SIZE {
134 return Err(error(format!("Failed to deserialize data ({num_bytes} bytes)")));
135 }
136 let mut bytes = Vec::new();
138 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
139 Ok(Self::Buffer(Bytes::from(bytes)))
141 }
142}
143
144impl<T: FromBytes + ToBytes + Send + 'static> ToBytes for Data<T> {
145 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
147 1u8.write_le(&mut writer)?;
149
150 match self {
152 Self::Object(object) => {
153 let buffer =
155 object.to_bytes_le().map_err(|e| error(format!("Failed to serialize 'Data::Object' - {e}")))?;
156 u32::try_from(buffer.len()).map_err(error)?.write_le(&mut writer)?;
158 writer.write_all(&buffer)
160 }
161 Self::Buffer(buffer) => {
162 u32::try_from(buffer.len()).map_err(error)?.write_le(&mut writer)?;
164 writer.write_all(buffer)
166 }
167 }
168 }
169}
170
171impl<T: FromBytes + ToBytes + Serialize + Send + 'static> Serialize for Data<T> {
172 #[inline]
174 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
175 match serializer.is_human_readable() {
176 true => {
177 let mut data = serializer.serialize_struct("Data", 2)?;
178 match self {
179 Self::Object(object) => {
180 data.serialize_field("type", "object")?;
181 data.serialize_field("data", object)?;
182 }
183 Self::Buffer(buffer) => {
184 use console::prelude::ser::Error;
185
186 data.serialize_field("type", "buffer")?;
187
188 let buffer = bech32::encode(PREFIX, buffer.to_vec().to_base32(), bech32::Variant::Bech32m)
190 .map_err(|_| S::Error::custom("Failed to encode data into bech32m"))?;
191
192 data.serialize_field("data", &buffer)?;
194 }
195 }
196 data.end()
197 }
198 false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
199 }
200 }
201}
202
203impl<'de, T: FromBytes + ToBytes + DeserializeOwned + Send + 'static> Deserialize<'de> for Data<T> {
204 #[inline]
206 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
207 match deserializer.is_human_readable() {
208 true => {
209 let mut data = serde_json::Value::deserialize(deserializer)?;
210 let type_: String = DeserializeExt::take_from_value::<D>(&mut data, "type")?;
211
212 match type_.as_str() {
214 "object" => {
215 let object = DeserializeExt::take_from_value::<D>(&mut data, "data")?;
216 Ok(Self::Object(object))
217 }
218 "buffer" => {
219 let encoding: String = DeserializeExt::take_from_value::<D>(&mut data, "data")?;
220
221 let (hrp, data, variant) = bech32::decode(&encoding).map_err(de::Error::custom)?;
223 if hrp != PREFIX {
224 return Err(de::Error::custom(error(format!("Invalid data HRP - {hrp}"))));
225 };
226 if data.is_empty() {
227 return Err(de::Error::custom(error("Invalid bech32m data (empty)")));
228 }
229 if variant != bech32::Variant::Bech32m {
230 return Err(de::Error::custom(error("Invalid data - variant is not bech32m")));
231 }
232 Ok(Self::Buffer(Bytes::from(Vec::from_base32(&data).map_err(de::Error::custom)?)))
233 }
234 _ => Err(de::Error::custom(error(format!("Invalid data type - {type_}")))),
235 }
236 }
237 false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "data"),
238 }
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245 use console::network::MainnetV0;
246 use ledger_block::Transaction;
247
248 #[test]
249 fn test_to_checksum() {
250 let rng = &mut TestRng::default();
251
252 let transactions = [
254 ledger_test_helpers::sample_deployment_transaction(true, rng),
255 ledger_test_helpers::sample_deployment_transaction(false, rng),
256 ledger_test_helpers::sample_execution_transaction_with_fee(true, rng),
257 ledger_test_helpers::sample_execution_transaction_with_fee(false, rng),
258 ledger_test_helpers::sample_fee_private_transaction(rng),
259 ledger_test_helpers::sample_fee_public_transaction(rng),
260 ];
261
262 for transaction in transactions.into_iter() {
263 let data_bytes: Data<Transaction<MainnetV0>> = Data::Buffer(transaction.to_bytes_le().unwrap().into());
265 let data = Data::Object(transaction);
267
268 let checksum_1 = data_bytes.to_checksum::<MainnetV0>().unwrap();
270 let checksum_2 = data.to_checksum::<MainnetV0>().unwrap();
271
272 assert_eq!(checksum_1, checksum_2);
274 }
275 }
276}