/ ledger / block / src / transition / serialize.rs
serialize.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the deltavm 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 Transition<N> {
 19      /// Serializes the transition 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 => {
 23                  let mut transition = serializer.serialize_struct("Transition", 8)?;
 24                  transition.serialize_field("id", &self.id)?;
 25                  transition.serialize_field("program", &self.program_id)?;
 26                  transition.serialize_field("function", &self.function_name)?;
 27                  transition.serialize_field("inputs", &self.inputs)?;
 28                  transition.serialize_field("outputs", &self.outputs)?;
 29                  transition.serialize_field("tpk", &self.tpk)?;
 30                  transition.serialize_field("tcm", &self.tcm)?;
 31                  transition.serialize_field("scm", &self.scm)?;
 32                  transition.end()
 33              }
 34              false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
 35          }
 36      }
 37  }
 38  
 39  impl<'de, N: Network> Deserialize<'de> for Transition<N> {
 40      /// Deserializes the transition from a string or bytes.
 41      fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
 42          match deserializer.is_human_readable() {
 43              true => {
 44                  // Parse the transition from a string into a value.
 45                  let mut transition = serde_json::Value::deserialize(deserializer)?;
 46                  // Retrieve the ID.
 47                  let id: N::TransitionID = DeserializeExt::take_from_value::<D>(&mut transition, "id")?;
 48  
 49                  // Recover the transition.
 50                  let transition = Self::new(
 51                      // Retrieve the program ID.
 52                      DeserializeExt::take_from_value::<D>(&mut transition, "program")?,
 53                      // Retrieve the function name.
 54                      DeserializeExt::take_from_value::<D>(&mut transition, "function")?,
 55                      // Retrieve the inputs.
 56                      DeserializeExt::take_from_value::<D>(&mut transition, "inputs")?,
 57                      // Retrieve the outputs.
 58                      DeserializeExt::take_from_value::<D>(&mut transition, "outputs")?,
 59                      // Retrieve the `tpk`.
 60                      DeserializeExt::take_from_value::<D>(&mut transition, "tpk")?,
 61                      // Retrieve the `tcm`.
 62                      DeserializeExt::take_from_value::<D>(&mut transition, "tcm")?,
 63                      // Retrieve the `scm`.
 64                      DeserializeExt::take_from_value::<D>(&mut transition, "scm")?,
 65                  )
 66                  .map_err(de::Error::custom)?;
 67  
 68                  // Ensure the transition ID is correct.
 69                  match id == *transition.id() {
 70                      true => Ok(transition),
 71                      false => Err(de::Error::custom(error("Transition ID mismatch, possible data corruption"))),
 72                  }
 73              }
 74              false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "transition"),
 75          }
 76      }
 77  }
 78  
 79  #[cfg(test)]
 80  mod tests {
 81      use super::*;
 82  
 83      #[test]
 84      fn test_serde_json() -> Result<()> {
 85          let rng = &mut TestRng::default();
 86  
 87          // Sample the transition.
 88          let expected = crate::transition::test_helpers::sample_transition(rng);
 89  
 90          // Serialize
 91          let expected_string = &expected.to_string();
 92          let candidate_string = serde_json::to_string(&expected)?;
 93          assert_eq!(expected, serde_json::from_str(&candidate_string)?);
 94  
 95          // Deserialize
 96          assert_eq!(expected, Transition::from_str(expected_string)?);
 97          assert_eq!(expected, serde_json::from_str(&candidate_string)?);
 98  
 99          Ok(())
100      }
101  
102      #[test]
103      fn test_bincode() -> Result<()> {
104          let rng = &mut TestRng::default();
105  
106          // Sample the transition.
107          let expected = crate::transition::test_helpers::sample_transition(rng);
108  
109          // Serialize
110          let expected_bytes = expected.to_bytes_le()?;
111          let expected_bytes_with_size_encoding = bincode::serialize(&expected)?;
112          assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
113  
114          // Deserialize
115          assert_eq!(expected, Transition::read_le(&expected_bytes[..])?);
116          assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..])?);
117  
118          Ok(())
119      }
120  }