cardano_serialization_lib/serialization/
transaction_body.rs

1use crate::*;
2
3impl cbor_event::se::Serialize for TransactionBody {
4    fn serialize<'se, W: Write>(
5        &self,
6        serializer: &'se mut Serializer<W>,
7    ) -> cbor_event::Result<&'se mut Serializer<W>> {
8        serializer.write_map(cbor_event::Len::Len(
9            3 + opt64(&self.ttl)
10                + opt64_non_empty(&self.certs)
11                + opt64_non_empty(&self.withdrawals)
12                + opt64(&self.update)
13                + opt64(&self.auxiliary_data_hash)
14                + opt64(&self.validity_start_interval)
15                + opt64_non_empty(&self.mint)
16                + opt64(&self.script_data_hash)
17                + opt64_non_empty(&self.collateral)
18                + opt64_non_empty(&self.required_signers)
19                + opt64(&self.network_id)
20                + opt64(&self.collateral_return)
21                + opt64(&self.total_collateral)
22                + opt64_non_empty(&self.reference_inputs)
23                + opt64_non_empty(&self.voting_procedures)
24                + opt64_non_empty(&self.voting_proposals)
25                + opt64(&self.donation)
26                + opt64(&self.current_treasury_value),
27        ))?;
28        serializer.write_unsigned_integer(0)?;
29        self.inputs.serialize(serializer)?;
30        serializer.write_unsigned_integer(1)?;
31        self.outputs.serialize(serializer)?;
32        serializer.write_unsigned_integer(2)?;
33        self.fee.serialize(serializer)?;
34        if let Some(field) = &self.ttl {
35            serializer.write_unsigned_integer(3)?;
36            field.serialize(serializer)?;
37        }
38        if let Some(field) = &self.certs {
39            if !field.is_none_or_empty() {
40                serializer.write_unsigned_integer(4)?;
41                field.serialize(serializer)?;
42            }
43        }
44        if let Some(field) = &self.withdrawals {
45            if !field.is_none_or_empty() {
46                serializer.write_unsigned_integer(5)?;
47                field.serialize(serializer)?;
48            }
49        }
50        if let Some(field) = &self.update {
51            serializer.write_unsigned_integer(6)?;
52            field.serialize(serializer)?;
53        }
54        if let Some(field) = &self.auxiliary_data_hash {
55            serializer.write_unsigned_integer(7)?;
56            field.serialize(serializer)?;
57        }
58        if let Some(field) = &self.validity_start_interval {
59            serializer.write_unsigned_integer(8)?;
60            field.serialize(serializer)?;
61        }
62        if let Some(field) = &self.mint {
63            if !field.is_none_or_empty() {
64                serializer.write_unsigned_integer(9)?;
65                field.serialize(serializer)?;
66            }
67        }
68        if let Some(field) = &self.script_data_hash {
69            serializer.write_unsigned_integer(11)?;
70            field.serialize(serializer)?;
71        }
72        if let Some(field) = &self.collateral {
73            if !field.is_none_or_empty() {
74                serializer.write_unsigned_integer(13)?;
75                field.serialize(serializer)?;
76            }
77        }
78        if let Some(field) = &self.required_signers {
79            if !field.is_none_or_empty() {
80                serializer.write_unsigned_integer(14)?;
81                field.serialize(serializer)?;
82            }
83        }
84        if let Some(field) = &self.network_id {
85            serializer.write_unsigned_integer(15)?;
86            field.serialize(serializer)?;
87        }
88        if let Some(field) = &self.collateral_return {
89            serializer.write_unsigned_integer(16)?;
90            field.serialize(serializer)?;
91        }
92        if let Some(field) = &self.total_collateral {
93            serializer.write_unsigned_integer(17)?;
94            field.serialize(serializer)?;
95        }
96        if let Some(field) = &self.reference_inputs {
97            if !field.is_none_or_empty() {
98                serializer.write_unsigned_integer(18)?;
99                field.serialize(serializer)?;
100            }
101        }
102        if let Some(field) = &self.voting_procedures {
103            if !field.is_none_or_empty() {
104                serializer.write_unsigned_integer(19)?;
105                field.serialize(serializer)?;
106            }
107        }
108        if let Some(field) = &self.voting_proposals {
109            if !field.is_none_or_empty() {
110                serializer.write_unsigned_integer(20)?;
111                field.serialize(serializer)?;
112            }
113        }
114        if let Some(field) = &self.current_treasury_value {
115            serializer.write_unsigned_integer(21)?;
116            field.serialize(serializer)?;
117        }
118        if let Some(field) = &self.donation {
119            serializer.write_unsigned_integer(22)?;
120            field.serialize(serializer)?;
121        }
122        Ok(serializer)
123    }
124}
125
126impl Deserialize for TransactionBody {
127    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
128        (|| -> Result<_, DeserializeError> {
129            let len = raw.map()?;
130            let mut read_len = CBORReadLen::new(len);
131            read_len.read_elems(3)?;
132            let mut inputs = None;
133            let mut outputs = None;
134            let mut fee = None;
135            let mut ttl = None;
136            let mut certs = None;
137            let mut withdrawals = None;
138            let mut update = None;
139            let mut auxiliary_data_hash = None;
140            let mut validity_start_interval = None;
141            let mut mint = None;
142            let mut script_data_hash = None;
143            let mut collateral = None;
144            let mut required_signers = None;
145            let mut network_id = None;
146            let mut collateral_return = None;
147            let mut total_collateral = None;
148            let mut reference_inputs = None;
149            let mut voting_procedures = None;
150            let mut voting_proposals = None;
151            let mut current_treasury_value = None;
152            let mut donation = None;
153            let mut read = 0;
154            while match len {
155                cbor_event::Len::Len(n) => read < n as usize,
156                cbor_event::Len::Indefinite => true,
157            } {
158                match raw.cbor_type()? {
159                    CBORType::UnsignedInteger => match raw.unsigned_integer()? {
160                        0 => {
161                            if inputs.is_some() {
162                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into());
163                            }
164                            inputs = Some(
165                                (|| -> Result<_, DeserializeError> {
166                                    Ok(TransactionInputs::deserialize(raw)?)
167                                })()
168                                    .map_err(|e| e.annotate("inputs"))?,
169                            );
170                        }
171                        1 => {
172                            if outputs.is_some() {
173                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into());
174                            }
175                            outputs = Some(
176                                (|| -> Result<_, DeserializeError> {
177                                    Ok(TransactionOutputs::deserialize(raw)?)
178                                })()
179                                    .map_err(|e| e.annotate("outputs"))?,
180                            );
181                        }
182                        2 => {
183                            if fee.is_some() {
184                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into());
185                            }
186                            fee =
187                                Some(
188                                    (|| -> Result<_, DeserializeError> {
189                                        Ok(Coin::deserialize(raw)?)
190                                    })()
191                                        .map_err(|e| e.annotate("fee"))?,
192                                );
193                        }
194                        3 => {
195                            if ttl.is_some() {
196                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into());
197                            }
198                            ttl = Some(
199                                (|| -> Result<_, DeserializeError> {
200                                    read_len.read_elems(1)?;
201                                    Ok(SlotBigNum::deserialize(raw)?)
202                                })()
203                                    .map_err(|e| e.annotate("ttl"))?,
204                            );
205                        }
206                        4 => {
207                            if certs.is_some() {
208                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into());
209                            }
210                            certs = Some(
211                                (|| -> Result<_, DeserializeError> {
212                                    read_len.read_elems(1)?;
213                                    Ok(Certificates::deserialize(raw)?)
214                                })()
215                                    .map_err(|e| e.annotate("certs"))?,
216                            );
217                        }
218                        5 => {
219                            if withdrawals.is_some() {
220                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(5)).into());
221                            }
222                            withdrawals = Some(
223                                (|| -> Result<_, DeserializeError> {
224                                    read_len.read_elems(1)?;
225                                    Ok(Withdrawals::deserialize(raw)?)
226                                })()
227                                    .map_err(|e| e.annotate("withdrawals"))?,
228                            );
229                        }
230                        6 => {
231                            if update.is_some() {
232                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(6)).into());
233                            }
234                            update = Some(
235                                (|| -> Result<_, DeserializeError> {
236                                    read_len.read_elems(1)?;
237                                    Ok(Update::deserialize(raw)?)
238                                })()
239                                    .map_err(|e| e.annotate("update"))?,
240                            );
241                        }
242                        7 => {
243                            if auxiliary_data_hash.is_some() {
244                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(7)).into());
245                            }
246                            auxiliary_data_hash = Some(
247                                (|| -> Result<_, DeserializeError> {
248                                    read_len.read_elems(1)?;
249                                    Ok(AuxiliaryDataHash::deserialize(raw)?)
250                                })()
251                                    .map_err(|e| e.annotate("auxiliary_data_hash"))?,
252                            );
253                        }
254                        8 => {
255                            if validity_start_interval.is_some() {
256                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(8)).into());
257                            }
258                            validity_start_interval = Some(
259                                (|| -> Result<_, DeserializeError> {
260                                    read_len.read_elems(1)?;
261                                    Ok(SlotBigNum::deserialize(raw)?)
262                                })()
263                                    .map_err(|e| e.annotate("validity_start_interval"))?,
264                            );
265                        }
266                        9 => {
267                            if mint.is_some() {
268                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(9)).into());
269                            }
270                            mint = Some(
271                                (|| -> Result<_, DeserializeError> {
272                                    read_len.read_elems(1)?;
273                                    Ok(Mint::deserialize(raw)?)
274                                })()
275                                    .map_err(|e| e.annotate("mint"))?,
276                            );
277                        }
278                        11 => {
279                            if script_data_hash.is_some() {
280                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(11)).into());
281                            }
282                            script_data_hash = Some(
283                                (|| -> Result<_, DeserializeError> {
284                                    read_len.read_elems(1)?;
285                                    Ok(ScriptDataHash::deserialize(raw)?)
286                                })()
287                                    .map_err(|e| e.annotate("script_data_hash"))?,
288                            );
289                        }
290                        13 => {
291                            if collateral.is_some() {
292                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(13)).into());
293                            }
294                            collateral = Some(
295                                (|| -> Result<_, DeserializeError> {
296                                    read_len.read_elems(1)?;
297                                    Ok(TransactionInputs::deserialize(raw)?)
298                                })()
299                                    .map_err(|e| e.annotate("collateral"))?,
300                            );
301                        }
302                        14 => {
303                            if required_signers.is_some() {
304                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(14)).into());
305                            }
306                            required_signers = Some(
307                                (|| -> Result<_, DeserializeError> {
308                                    read_len.read_elems(1)?;
309                                    Ok(Ed25519KeyHashes::deserialize(raw)?)
310                                })()
311                                    .map_err(|e| e.annotate("required_signers"))?,
312                            );
313                        }
314                        15 => {
315                            if network_id.is_some() {
316                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(15)).into());
317                            }
318                            network_id = Some(
319                                (|| -> Result<_, DeserializeError> {
320                                    read_len.read_elems(1)?;
321                                    Ok(NetworkId::deserialize(raw)?)
322                                })()
323                                    .map_err(|e| e.annotate("network_id"))?,
324                            );
325                        }
326                        16 => {
327                            if collateral_return.is_some() {
328                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(16)).into());
329                            }
330                            collateral_return = Some(
331                                (|| -> Result<_, DeserializeError> {
332                                    read_len.read_elems(1)?;
333                                    Ok(TransactionOutput::deserialize(raw)?)
334                                })()
335                                    .map_err(|e| e.annotate("collateral_return"))?,
336                            );
337                        }
338                        17 => {
339                            if total_collateral.is_some() {
340                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(17)).into());
341                            }
342                            total_collateral = Some(
343                                (|| -> Result<_, DeserializeError> {
344                                    read_len.read_elems(1)?;
345                                    Ok(Coin::deserialize(raw)?)
346                                })()
347                                    .map_err(|e| e.annotate("total_collateral"))?,
348                            );
349                        }
350                        18 => {
351                            if reference_inputs.is_some() {
352                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(18)).into());
353                            }
354                            reference_inputs = Some(
355                                (|| -> Result<_, DeserializeError> {
356                                    read_len.read_elems(1)?;
357                                    Ok(TransactionInputs::deserialize(raw)?)
358                                })()
359                                    .map_err(|e| e.annotate("reference_inputs"))?,
360                            );
361                        }
362                        19 => {
363                            if voting_procedures.is_some() {
364                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(19)).into());
365                            }
366                            voting_procedures = Some(
367                                (|| -> Result<_, DeserializeError> {
368                                    read_len.read_elems(1)?;
369                                    Ok(VotingProcedures::deserialize(raw)?)
370                                })()
371                                    .map_err(|e| e.annotate("voting_procedures"))?,
372                            );
373                        }
374                        20 => {
375                            if voting_proposals.is_some() {
376                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(20)).into());
377                            }
378                            voting_proposals = Some(
379                                (|| -> Result<_, DeserializeError> {
380                                    read_len.read_elems(1)?;
381                                    Ok(VotingProposals::deserialize(raw)?)
382                                })()
383                                    .map_err(|e| e.annotate("voting_proposals"))?,
384                            );
385                        }
386                        21 => {
387                            if current_treasury_value.is_some() {
388                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(21)).into());
389                            }
390                            current_treasury_value = Some(
391                                (|| -> Result<_, DeserializeError> {
392                                    read_len.read_elems(1)?;
393                                    Ok(Coin::deserialize(raw)?)
394                                })()
395                                    .map_err(|e| e.annotate("current_treasury_value"))?,
396                            );
397                        }
398                        22 => {
399                            if donation.is_some() {
400                                return Err(DeserializeFailure::DuplicateKey(Key::Uint(22)).into());
401                            }
402                            donation = Some(
403                                (|| -> Result<_, DeserializeError> {
404                                    read_len.read_elems(1)?;
405                                    Ok(Coin::deserialize(raw)?)
406                                })()
407                                    .map_err(|e| e.annotate("donation"))?,
408                            );
409                        }
410                        unknown_key => {
411                            return Err(
412                                DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into()
413                            )
414                        }
415                    },
416                    CBORType::Text => match raw.text()?.as_str() {
417                        unknown_key => {
418                            return Err(DeserializeFailure::UnknownKey(Key::Str(
419                                unknown_key.to_owned(),
420                            ))
421                                .into())
422                        }
423                    },
424                    CBORType::Special => match len {
425                        cbor_event::Len::Len(_) => {
426                            return Err(DeserializeFailure::BreakInDefiniteLen.into())
427                        }
428                        cbor_event::Len::Indefinite => match raw.special()? {
429                            CBORSpecial::Break => break,
430                            _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
431                        },
432                    },
433                    other_type => {
434                        return Err(DeserializeFailure::UnexpectedKeyType(other_type).into())
435                    }
436                }
437                read += 1;
438            }
439            let inputs = match inputs {
440                Some(x) => x,
441                None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(0)).into()),
442            };
443            let outputs = match outputs {
444                Some(x) => x,
445                None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(1)).into()),
446            };
447            let fee = match fee {
448                Some(x) => x,
449                None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(2)).into()),
450            };
451            read_len.finish()?;
452            Ok(Self {
453                inputs,
454                outputs,
455                fee,
456                ttl,
457                certs,
458                withdrawals,
459                update,
460                auxiliary_data_hash,
461                validity_start_interval,
462                mint,
463                script_data_hash,
464                collateral,
465                required_signers,
466                network_id,
467                collateral_return,
468                total_collateral,
469                reference_inputs,
470                voting_procedures,
471                voting_proposals,
472                donation,
473                current_treasury_value,
474            })
475        })()
476            .map_err(|e| e.annotate("TransactionBody"))
477    }
478}