snarkvm_ledger_block/transaction/
serialize.rs1use super::*;
17
18impl<N: Network> Serialize for Transaction<N> {
19 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
21 match serializer.is_human_readable() {
24 true => match self {
25 Self::Deploy(id, _, owner, deployment, fee) => {
26 let mut transaction = serializer.serialize_struct("Transaction", 5)?;
27 transaction.serialize_field("type", "deploy")?;
28 transaction.serialize_field("id", &id)?;
29 transaction.serialize_field("owner", &owner)?;
30 transaction.serialize_field("deployment", &deployment)?;
31 transaction.serialize_field("fee", &fee)?;
32 transaction.end()
33 }
34 Self::Execute(id, _, execution, fee) => {
35 let mut transaction = serializer.serialize_struct("Transaction", 3 + fee.is_some() as usize)?;
36 transaction.serialize_field("type", "execute")?;
37 transaction.serialize_field("id", &id)?;
38 transaction.serialize_field("execution", &execution)?;
39 if let Some(fee) = fee {
40 transaction.serialize_field("fee", &fee)?;
41 }
42 transaction.end()
43 }
44 Self::Fee(id, fee) => {
45 let mut transaction = serializer.serialize_struct("Transaction", 3)?;
46 transaction.serialize_field("type", "fee")?;
47 transaction.serialize_field("id", &id)?;
48 transaction.serialize_field("fee", &fee)?;
49 transaction.end()
50 }
51 },
52 false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
53 }
54 }
55}
56
57impl<'de, N: Network> Deserialize<'de> for Transaction<N> {
58 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
60 match deserializer.is_human_readable() {
61 true => {
62 let mut transaction = serde_json::Value::deserialize(deserializer)?;
64 let id: N::TransactionID = DeserializeExt::take_from_value::<D>(&mut transaction, "id")?;
66
67 let transaction = match transaction
69 .get("type")
70 .ok_or_else(|| de::Error::custom("The \"type\" field is missing"))?
71 .as_str()
72 {
73 Some("deploy") => {
74 let owner = DeserializeExt::take_from_value::<D>(&mut transaction, "owner")?;
76 let deployment = DeserializeExt::take_from_value::<D>(&mut transaction, "deployment")?;
78 let fee = DeserializeExt::take_from_value::<D>(&mut transaction, "fee")?;
80 Transaction::from_deployment(owner, deployment, fee).map_err(de::Error::custom)?
82 }
83 Some("execute") => {
84 let execution = DeserializeExt::take_from_value::<D>(&mut transaction, "execution")?;
86 let fee = serde_json::from_value(
88 transaction.get_mut("fee").unwrap_or(&mut serde_json::Value::Null).take(),
89 )
90 .map_err(de::Error::custom)?;
91 Transaction::from_execution(execution, fee).map_err(de::Error::custom)?
93 }
94 Some("fee") => {
95 let fee = DeserializeExt::take_from_value::<D>(&mut transaction, "fee")?;
97 Transaction::from_fee(fee).map_err(de::Error::custom)?
99 }
100 _ => return Err(de::Error::custom("Invalid transaction type")),
101 };
102
103 match id == transaction.id() {
105 true => Ok(transaction),
106 false => Err(de::Error::custom(error("Mismatching transaction ID, possible data corruption"))),
107 }
108 }
109 false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "transaction"),
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_serde_json() -> Result<()> {
120 let rng = &mut TestRng::default();
121
122 for expected in [
123 crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), true, rng),
124 crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), false, rng),
125 crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), true, rng),
126 crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), false, rng),
127 crate::transaction::test_helpers::sample_execution_transaction_with_fee(true, rng, 0),
128 crate::transaction::test_helpers::sample_execution_transaction_with_fee(false, rng, 0),
129 ]
130 .into_iter()
131 {
132 let expected_string = &expected.to_string();
134 let candidate_string = serde_json::to_string(&expected)?;
135
136 assert_eq!(expected, Transaction::from_str(expected_string)?);
138 assert_eq!(expected, serde_json::from_str(&candidate_string)?);
139 }
140 Ok(())
141 }
142
143 #[test]
144 fn test_bincode() -> Result<()> {
145 let rng = &mut TestRng::default();
146
147 for expected in [
148 crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), true, rng),
149 crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), false, rng),
150 crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), true, rng),
151 crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), false, rng),
152 crate::transaction::test_helpers::sample_execution_transaction_with_fee(true, rng, 0),
153 crate::transaction::test_helpers::sample_execution_transaction_with_fee(false, rng, 0),
154 ]
155 .into_iter()
156 {
157 let expected_bytes = expected.to_bytes_le()?;
159 let expected_bytes_with_size_encoding = bincode::serialize(&expected)?;
160 assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
161
162 assert_eq!(expected, Transaction::read_le(&expected_bytes[..])?);
164 assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..])?);
165 }
166 Ok(())
167 }
168}