/ ledger / block / src / transactions / confirmed / serialize.rs
serialize.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use super::*;
 17  
 18  impl<N: Network> Serialize for ConfirmedTransaction<N> {
 19      /// Serializes the confirmed transaction into string or bytes.
 20      fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
 21          match serializer.is_human_readable() {
 22              true => match self {
 23                  Self::AcceptedDeploy(index, transaction, finalize_operations) => {
 24                      let mut object = serializer.serialize_struct("ConfirmedTransaction", 5)?;
 25                      object.serialize_field("status", "accepted")?;
 26                      object.serialize_field("type", "deploy")?;
 27                      object.serialize_field("index", index)?;
 28                      object.serialize_field("transaction", transaction)?;
 29                      object.serialize_field("finalize", finalize_operations)?;
 30                      object.end()
 31                  }
 32                  Self::AcceptedExecute(index, transaction, finalize_operations) => {
 33                      let mut object = serializer.serialize_struct("ConfirmedTransaction", 5)?;
 34                      object.serialize_field("status", "accepted")?;
 35                      object.serialize_field("type", "execute")?;
 36                      object.serialize_field("index", index)?;
 37                      object.serialize_field("transaction", transaction)?;
 38                      object.serialize_field("finalize", finalize_operations)?;
 39                      object.end()
 40                  }
 41                  Self::RejectedDeploy(index, transaction, rejected_deployment, finalize_operations) => {
 42                      let mut object = serializer.serialize_struct("ConfirmedTransaction", 6)?;
 43                      object.serialize_field("status", "rejected")?;
 44                      object.serialize_field("type", "deploy")?;
 45                      object.serialize_field("index", index)?;
 46                      object.serialize_field("transaction", transaction)?;
 47                      object.serialize_field("rejected", &rejected_deployment)?;
 48                      object.serialize_field("finalize", finalize_operations)?;
 49                      object.end()
 50                  }
 51                  Self::RejectedExecute(index, transaction, rejected_execution, finalize_operations) => {
 52                      let mut object = serializer.serialize_struct("ConfirmedTransaction", 6)?;
 53                      object.serialize_field("status", "rejected")?;
 54                      object.serialize_field("type", "execute")?;
 55                      object.serialize_field("index", index)?;
 56                      object.serialize_field("transaction", transaction)?;
 57                      object.serialize_field("rejected", &rejected_execution)?;
 58                      object.serialize_field("finalize", finalize_operations)?;
 59                      object.end()
 60                  }
 61              },
 62              false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
 63          }
 64      }
 65  }
 66  
 67  impl<'de, N: Network> Deserialize<'de> for ConfirmedTransaction<N> {
 68      /// Deserializes the confirmed transaction from a string or bytes.
 69      fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
 70          match deserializer.is_human_readable() {
 71              true => {
 72                  // Parse the confirmed transaction from a string into a value.
 73                  let mut object = serde_json::Value::deserialize(deserializer)?;
 74  
 75                  // Parse the index.
 76                  let index: u32 = DeserializeExt::take_from_value::<D>(&mut object, "index")?;
 77                  // Parse the transaction.
 78                  let transaction: Transaction<N> = DeserializeExt::take_from_value::<D>(&mut object, "transaction")?;
 79  
 80                  // Parse the status and type.
 81                  let status = object.get("status").and_then(|t| t.as_str());
 82                  let type_ = object.get("type").and_then(|t| t.as_str());
 83  
 84                  // Recover the confirmed transaction.
 85                  match (status, type_) {
 86                      (Some("accepted"), Some("deploy")) => {
 87                          // Parse the finalize operations.
 88                          let finalize: Vec<_> = DeserializeExt::take_from_value::<D>(&mut object, "finalize")?;
 89                          // Return the accepted deploy transaction.
 90                          Self::accepted_deploy(index, transaction, finalize).map_err(de::Error::custom)
 91                      }
 92                      (Some("accepted"), Some("execute")) => {
 93                          // Parse the finalize operations.
 94                          let finalize: Vec<_> = DeserializeExt::take_from_value::<D>(&mut object, "finalize")?;
 95                          // Return the accepted execute transaction.
 96                          Self::accepted_execute(index, transaction, finalize).map_err(de::Error::custom)
 97                      }
 98                      (Some("rejected"), Some("deploy")) => {
 99                          // Parse the rejected deployment.
100                          let rejected: Rejected<N> = DeserializeExt::take_from_value::<D>(&mut object, "rejected")?;
101                          // Parse the finalize operations.
102                          let finalize: Vec<_> = DeserializeExt::take_from_value::<D>(&mut object, "finalize")?;
103                          // Return the rejected deploy transaction.
104                          Self::rejected_deploy(index, transaction, rejected, finalize).map_err(de::Error::custom)
105                      }
106                      (Some("rejected"), Some("execute")) => {
107                          // Parse the rejected execution.
108                          let rejected: Rejected<N> = DeserializeExt::take_from_value::<D>(&mut object, "rejected")?;
109                          // Parse the finalize operations.
110                          let finalize: Vec<_> = DeserializeExt::take_from_value::<D>(&mut object, "finalize")?;
111                          // Return the rejected execute transaction.
112                          Self::rejected_execute(index, transaction, rejected, finalize).map_err(de::Error::custom)
113                      }
114                      _ => Err(de::Error::custom("Invalid confirmed transaction type")),
115                  }
116              }
117              false => {
118                  FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "confirmed transaction")
119              }
120          }
121      }
122  }
123  
124  #[cfg(test)]
125  mod tests {
126      use super::*;
127  
128      fn check_serde_json<
129          T: Serialize + for<'a> Deserialize<'a> + Debug + Display + PartialEq + Eq + FromStr + ToBytes + FromBytes,
130      >(
131          expected: T,
132      ) {
133          // Serialize
134          let expected_string = expected.to_string();
135          let candidate_string = serde_json::to_string(&expected).unwrap();
136          let candidate = serde_json::from_str::<T>(&candidate_string).unwrap();
137          assert_eq!(expected, candidate);
138          assert_eq!(expected_string, candidate_string);
139          assert_eq!(expected_string, candidate.to_string());
140  
141          // Deserialize
142          assert_eq!(expected, T::from_str(&expected_string).unwrap_or_else(|_| panic!("FromStr: {expected_string}")));
143          assert_eq!(expected, serde_json::from_str(&candidate_string).unwrap());
144      }
145  
146      fn check_bincode<
147          T: Serialize + for<'a> Deserialize<'a> + Debug + Display + PartialEq + Eq + FromStr + ToBytes + FromBytes,
148      >(
149          expected: T,
150      ) {
151          // Serialize
152          let expected_bytes = expected.to_bytes_le().unwrap();
153          let expected_bytes_with_size_encoding = bincode::serialize(&expected).unwrap();
154          assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
155  
156          // Deserialize
157          assert_eq!(expected, T::read_le(&expected_bytes[..]).unwrap());
158          assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..]).unwrap());
159      }
160  
161      #[test]
162      fn test_serde_json() {
163          for transaction in crate::transactions::confirmed::test_helpers::sample_confirmed_transactions() {
164              check_serde_json(transaction);
165          }
166      }
167  
168      #[test]
169      fn test_bincode() {
170          for transaction in crate::transactions::confirmed::test_helpers::sample_confirmed_transactions() {
171              check_bincode(transaction);
172          }
173      }
174  }