1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::*;
use std::io::SeekFrom;

impl cbor_event::se::Serialize for FixedTransaction {
    fn serialize<'se, W: Write>(
        &self,
        serializer: &'se mut Serializer<W>,
    ) -> cbor_event::Result<&'se mut Serializer<W>> {
        serializer.write_array(cbor_event::Len::Len(4))?;
        serializer.write_raw_bytes(&self.body_bytes)?;
        serializer.write_raw_bytes(&self.witness_bytes)?;
        serializer.write_special(CBORSpecial::Bool(self.is_valid))?;
        match &self.auxiliary_bytes {
            Some(auxiliary_bytes) => serializer.write_raw_bytes(auxiliary_bytes)?,
            None => serializer.write_special(CBORSpecial::Null)?,
        };
        Ok(serializer)
    }
}

impl Deserialize for FixedTransaction {
    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
        (|| -> Result<_, DeserializeError> {
            let len = raw.array()?;
            let ret = Self::deserialize_as_embedded_group(raw, len);
            match len {
                cbor_event::Len::Len(_) =>
                /* TODO: check finite len somewhere */
                {
                    ()
                }
                cbor_event::Len::Indefinite => match raw.special()? {
                    CBORSpecial::Break =>
                    /* it's ok */
                    {
                        ()
                    }
                    _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
                },
            }
            ret
        })()
        .map_err(|e| e.annotate("Transaction"))
    }
}

impl DeserializeEmbeddedGroup for FixedTransaction {
    fn deserialize_as_embedded_group<R: BufRead + Seek>(
        raw: &mut Deserializer<R>,
        _: cbor_event::Len,
    ) -> Result<Self, DeserializeError> {
        let (body, body_bytes) =
            deserilized_with_orig_bytes(raw, |raw| TransactionBody::deserialize(raw))
                .map_err(|e| e.annotate("body"))?;
        let (witness_set, witness_bytes) =
            deserilized_with_orig_bytes(raw, |raw| TransactionWitnessSet::deserialize(raw))
                .map_err(|e| e.annotate("witness_set"))?;
        let mut checked_auxiliary_data = false;
        let mut auxiliary_data = None;
        let mut auxiliary_bytes = None;
        let is_valid = (|| -> Result<_, DeserializeError> {
            match raw.cbor_type()? == CBORType::Special {
                true => {
                    // if it's special it can be either a bool or null. if it's null, then it's empty auxiliary data, otherwise not a valid encoding
                    let special = raw.special()?;
                    if let CBORSpecial::Bool(b) = special {
                        return Ok(b);
                    } else if special == CBORSpecial::Null {
                        checked_auxiliary_data = true;
                        return Ok(true);
                    } else {
                        return Err(DeserializeFailure::ExpectedBool.into());
                    }
                }
                false => {
                    let (auxiliary_data_deser, auxiliary_bytes_deser) =
                        deserilized_with_orig_bytes(raw, |raw| AuxiliaryData::deserialize(raw))
                            .map_err(|e| e.annotate("auxiliary_data"))?;
                    auxiliary_data = Some(auxiliary_data_deser);
                    auxiliary_bytes = Some(auxiliary_bytes_deser);
                    // if no special symbol was detected, it must have auxiliary data
                    checked_auxiliary_data = true;
                    return Ok(true);
                }
            }
        })()
        .map_err(|e| e.annotate("is_valid"))?;
        if !checked_auxiliary_data {
            // this branch is reached, if the 3rd argument was a bool. then it simply follows the rules for checking auxiliary data
            (auxiliary_data, auxiliary_bytes) = (|| -> Result<_, DeserializeError> {
                Ok(match raw.cbor_type()? != CBORType::Special {
                    true => {
                        let (auxiliary_data_deser, auxiliary_bytes_deser) =
                            deserilized_with_orig_bytes(raw, |raw| {
                                AuxiliaryData::deserialize(raw)
                            })?;
                        (Some(auxiliary_data_deser), Some(auxiliary_bytes_deser))
                    }
                    false => {
                        if raw.special()? != CBORSpecial::Null {
                            return Err(DeserializeFailure::ExpectedNull.into());
                        }
                        (None, None)
                    }
                })
            })()
            .map_err(|e| e.annotate("auxiliary_data"))?;
        }
        Ok(FixedTransaction {
            body,
            body_bytes,
            witness_set,
            witness_bytes,
            is_valid,
            auxiliary_data,
            auxiliary_bytes,
        })
    }
}

fn deserilized_with_orig_bytes<R: BufRead + Seek, T>(
    raw: &mut Deserializer<R>,
    deserilizator: fn(&mut Deserializer<R>) -> Result<T, DeserializeError>,
) -> Result<(T, Vec<u8>), DeserializeError> {
    let before = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
    let value = deserilizator(raw)?;
    let after = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
    let bytes_read = (after - before) as usize;
    raw.as_mut_ref().seek(SeekFrom::Start(before)).unwrap();
    let original_bytes = raw.as_mut_ref().fill_buf().unwrap()[..bytes_read].to_vec();
    raw.as_mut_ref().seek(SeekFrom::Start(after)).unwrap();
    Ok((value, original_bytes))
}