cardano_serialization_lib/serialization/witnesses/
transaction_witnesses_set.rs

1use std::io::{BufRead, Seek, Write};
2use cbor_event::de::Deserializer;
3use cbor_event::se::Serializer;
4use cbor_event::Serialize;
5use crate::{BootstrapWitnesses, CBORReadLen, DeserializeError, DeserializeFailure, Key, Language, NativeScripts, PlutusList, PlutusScripts, Redeemers, TransactionWitnessSet, Vkeywitnesses};
6use crate::protocol_types::{CBORSpecial, CBORType, Deserialize, opt64, TransactionWitnessSetRaw};
7use crate::serialization::utils::{deserilized_with_orig_bytes, merge_option_plutus_list};
8use crate::traits::NoneOrEmpty;
9use crate::utils::opt64_non_empty;
10
11impl cbor_event::se::Serialize for TransactionWitnessSet {
12    fn serialize<'a, W: Write + Sized>(&self, serializer: &'a mut Serializer<W>) -> cbor_event::Result<&'a mut Serializer<W>> {
13        serialize(self, None, serializer)
14    }
15}
16
17impl Deserialize for TransactionWitnessSet {
18    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError>
19    where
20        Self: Sized
21    {
22        let (witness_set, _) = deserialize(raw, false)?;
23        Ok(witness_set)
24    }
25}
26
27pub(super) fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>, with_raw_parts: bool) -> Result<(TransactionWitnessSet, TransactionWitnessSetRaw), DeserializeError> {
28    (|| -> Result<_, DeserializeError> {
29        let len = raw.map()?;
30        let mut read_len = CBORReadLen::new(len);
31        let mut vkeys = None;
32        let mut native_scripts = None;
33        let mut bootstraps = None;
34        let mut plutus_scripts_v1 = None;
35        let mut plutus_scripts_v2 = None;
36        let mut plutus_scripts_v3 = None;
37        let mut plutus_data = None;
38        let mut redeemers = None;
39        let mut read = 0;
40        let mut raw_part = TransactionWitnessSetRaw::new();
41
42        while match len {
43            cbor_event::Len::Len(n) => read < n as usize,
44            cbor_event::Len::Indefinite => true,
45        } {
46            match raw.cbor_type()? {
47                CBORType::UnsignedInteger => match raw.unsigned_integer()? {
48                    0 => {
49                        if vkeys.is_some() {
50                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into());
51                        }
52                        read_len.read_elems(1)?;
53                        let (vkeys_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
54                            Vkeywitnesses::deserialize(raw)
55                        ).map_err(|e| e.annotate("vkeys"))?;
56
57                        vkeys = Some(vkeys_deser);
58                        if with_raw_parts {
59                            raw_part.vkeys = Some(raw);
60                        }
61                    }
62                    1 => {
63                        if native_scripts.is_some() {
64                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into());
65                        }
66                        read_len.read_elems(1)?;
67                        let (native_scripts_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
68                            NativeScripts::deserialize(raw)
69                        ).map_err(|e| e.annotate("native_scripts"))?;
70                        native_scripts = Some(native_scripts_deser);
71                        if with_raw_parts {
72                            raw_part.native_scripts = Some(raw);
73                        }
74                    }
75                    2 => {
76                        if bootstraps.is_some() {
77                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into());
78                        }
79                        read_len.read_elems(1)?;
80                        let (bootstraps_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
81                            BootstrapWitnesses::deserialize(raw)
82                        ).map_err(|e| e.annotate("bootstraps"))?;
83                        bootstraps = Some(bootstraps_deser);
84                        if with_raw_parts {
85                            raw_part.bootstraps = Some(raw);
86                        }
87                    }
88                    3 => {
89                        if plutus_scripts_v1.is_some() {
90                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into());
91                        }
92                        read_len.read_elems(1)?;
93                        let (plutus_scripts_v1_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
94                            PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v1())
95                        ).map_err(|e| e.annotate("plutus_scripts_v1"))?;
96                        plutus_scripts_v1 = Some(plutus_scripts_v1_deser);
97                        if with_raw_parts {
98                            raw_part.plutus_scripts_v1 = Some(raw);
99                        }
100                    }
101                    4 => {
102                        if plutus_data.is_some() {
103                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into());
104                        }
105                        read_len.read_elems(1)?;
106                        let (plutus_data_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
107                            PlutusList::deserialize(raw)
108                        ).map_err(|e| e.annotate("plutus_data"))?;
109                        plutus_data = Some(plutus_data_deser);
110                        if with_raw_parts {
111                            raw_part.plutus_data = Some(raw);
112                        }
113                    }
114                    5 => {
115                        if redeemers.is_some() {
116                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(5)).into());
117                        }
118                        read_len.read_elems(1)?;
119                        let (redeemers_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
120                            Redeemers::deserialize(raw)
121                        ).map_err(|e| e.annotate("redeemers"))?;
122                        redeemers = Some(redeemers_deser);
123                        if with_raw_parts {
124                            raw_part.redeemers = Some(raw);
125                        }
126                    }
127                    6 => {
128                        if plutus_scripts_v2.is_some() {
129                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(6)).into());
130                        }
131                        read_len.read_elems(1)?;
132                        let (plutus_scripts_v2_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
133                            PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v2())
134                        ).map_err(|e| e.annotate("plutus_scripts_v2"))?;
135                        plutus_scripts_v2 = Some(plutus_scripts_v2_deser);
136                        if with_raw_parts {
137                            raw_part.plutus_scripts_v2 = Some(raw);
138                        }
139                    }
140                    7 => {
141                        if plutus_scripts_v3.is_some() {
142                            return Err(DeserializeFailure::DuplicateKey(Key::Uint(7)).into());
143                        }
144                        read_len.read_elems(1)?;
145                        let (plutus_scripts_v3_deser, raw) = deserilized_with_orig_bytes(raw, |raw|
146                            PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v3())
147                        ).map_err(|e| e.annotate("plutus_scripts_v3"))?;
148                        plutus_scripts_v3 = Some(plutus_scripts_v3_deser);
149                        if with_raw_parts {
150                            raw_part.plutus_scripts_v3 = Some(raw);
151                        }
152                    }
153                    unknown_key => {
154                        return Err(
155                            DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into()
156                        )
157                    }
158                },
159                CBORType::Text => match raw.text()?.as_str() {
160                    unknown_key => {
161                        return Err(DeserializeFailure::UnknownKey(Key::Str(
162                            unknown_key.to_owned(),
163                        ))
164                            .into())
165                    }
166                },
167                CBORType::Special => match len {
168                    cbor_event::Len::Len(_) => {
169                        return Err(DeserializeFailure::BreakInDefiniteLen.into())
170                    }
171                    cbor_event::Len::Indefinite => match raw.special()? {
172                        CBORSpecial::Break => break,
173                        _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
174                    },
175                },
176                other_type => {
177                    return Err(DeserializeFailure::UnexpectedKeyType(other_type).into())
178                }
179            }
180            read += 1;
181        }
182        read_len.finish()?;
183        let mut plutus_scripts = None;
184        plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v1, &Language::new_plutus_v1());
185        plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v2, &Language::new_plutus_v2());
186        plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v3, &Language::new_plutus_v3());
187
188        Ok((TransactionWitnessSet {
189            vkeys,
190            native_scripts,
191            bootstraps,
192            plutus_scripts,
193            plutus_data,
194            redeemers,
195        }, raw_part))
196    })()
197        .map_err(|e| e.annotate("TransactionWitnessSet"))
198}
199
200pub(super) fn serialize<'se, W: Write>(
201    wit_set: &TransactionWitnessSet,
202    raw_parts: Option<&TransactionWitnessSetRaw>,
203    serializer: &'se mut Serializer<W>,
204) -> cbor_event::Result<&'se mut Serializer<W>> {
205    let mut has_plutus_v1 = false;
206    let mut has_plutus_v2 = false;
207    let mut has_plutus_v3 = false;
208    let plutus_added_length = match &wit_set.plutus_scripts {
209        Some(scripts) => {
210            has_plutus_v1 = scripts.has_version(&Language::new_plutus_v1());
211            has_plutus_v2 = scripts.has_version(&Language::new_plutus_v2());
212            has_plutus_v3 = scripts.has_version(&Language::new_plutus_v3());
213            (has_plutus_v1 as u64) + (has_plutus_v2 as u64) + (has_plutus_v3 as u64)
214        },
215        _ => 0,
216    };
217    serializer.write_map(cbor_event::Len::Len(
218        opt64(&wit_set.vkeys)
219            + opt64_non_empty(&wit_set.native_scripts)
220            + opt64_non_empty(&wit_set.bootstraps)
221            + opt64_non_empty(&wit_set.plutus_data)
222            + opt64_non_empty(&wit_set.redeemers)
223            + plutus_added_length,
224    ))?;
225    if let Some(field) = &wit_set.vkeys {
226        if let Some(raw_vkeys) = raw_parts.map(|x| x.vkeys.as_ref()).flatten() {
227            serializer.write_unsigned_integer(0)?;
228            serializer.write_raw_bytes(raw_vkeys)?;
229        } else if !field.is_none_or_empty() {
230            serializer.write_unsigned_integer(0)?;
231            field.serialize(serializer)?;
232        }
233    }
234    if let Some(field) = &wit_set.native_scripts {
235        if let Some(raw) = raw_parts.as_ref().map(|x| x.native_scripts.as_ref()).flatten() {
236            serializer.write_unsigned_integer(1)?;
237            serializer.write_raw_bytes(raw)?;
238        } else if !field.is_none_or_empty() {
239            serializer.write_unsigned_integer(1)?;
240            //transaction witness set already has deduplicated native scripts
241            field.serialize_as_set(false, serializer)?;
242        }
243    }
244    if let Some(field) = &wit_set.bootstraps {
245        if let Some(raw) = raw_parts.as_ref().map(|x| x.bootstraps.as_ref()).flatten() {
246            serializer.write_unsigned_integer(2)?;
247            serializer.write_raw_bytes(raw)?;
248        } else if !field.is_none_or_empty() {
249            serializer.write_unsigned_integer(2)?;
250            field.serialize(serializer)?;
251        }
252    }
253
254    //no need deduplication here because transaction witness set already has deduplicated plutus scripts
255    if let Some(plutus_scripts) = &wit_set.plutus_scripts {
256        if has_plutus_v1 {
257            if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v1.as_ref()).flatten() {
258                serializer.write_unsigned_integer(3)?;
259                serializer.write_raw_bytes(raw)?;
260            } else {
261                serializer.write_unsigned_integer(3)?;
262                plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v1(), serializer)?;
263            }
264        }
265        if has_plutus_v2 {
266            if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v2.as_ref()).flatten() {
267                serializer.write_unsigned_integer(6)?;
268                serializer.write_raw_bytes(raw)?;
269            } else {
270                serializer.write_unsigned_integer(6)?;
271                plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v2(), serializer)?;
272            }
273        }
274        if has_plutus_v3 {
275            if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v3.as_ref()).flatten() {
276                serializer.write_unsigned_integer(7)?;
277                serializer.write_raw_bytes(raw)?;
278            } else {
279                serializer.write_unsigned_integer(7)?;
280                plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v3(), serializer)?;
281            }
282        }
283    }
284    if let Some(field) = &wit_set.plutus_data {
285        if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_data.as_ref()).flatten() {
286            serializer.write_unsigned_integer(4)?;
287            serializer.write_raw_bytes(&raw)?;
288        } else if !field.is_none_or_empty() {
289            serializer.write_unsigned_integer(4)?;
290            //transaction witness set already has deduplicated plutus data
291            field.serialize_as_set(false, serializer)?;
292        }
293    }
294    if let Some(field) = &wit_set.redeemers {
295        if let Some(raw) = raw_parts.as_ref().map(|x| x.redeemers.as_ref()).flatten() {
296            serializer.write_unsigned_integer(5)?;
297            serializer.write_raw_bytes(raw)?;
298        } else if !field.is_none_or_empty() {
299            serializer.write_unsigned_integer(5)?;
300            field.serialize(serializer)?;
301        }
302    }
303    Ok(serializer)
304}