1use super::*;
5use cbor_event::de::Deserializer;
6use cbor_event::se::Serializer;
7use cbor_event::{self, LenSz};
8use cml_core::serialization::fit_sz;
9use cml_core::{
10 error::{DeserializeError, DeserializeFailure, Key},
11 serialization::{CBORReadLen, Deserialize},
12};
13use cml_crypto::RawBytesEncoding;
14use std::io::{BufRead, Seek, SeekFrom, Write};
15
16impl cbor_event::se::Serialize for AddrAttributes {
17 fn serialize<'se, W: Write>(
18 &self,
19 serializer: &'se mut Serializer<W>,
20 ) -> cbor_event::Result<&'se mut Serializer<W>> {
21 serializer.write_map(cbor_event::Len::Len(
25 match &self.stake_distribution {
26 Some(StakeDistribution::SingleKey(_)) => 1,
27 _ => 0,
28 } + match &self.derivation_path {
29 Some(_) => 1,
30 None => 0,
31 } + match &self.protocol_magic {
32 Some(_) => 1,
33 None => 0,
34 },
35 ))?;
36 if let Some(StakeDistribution::SingleKey(_)) = &self.stake_distribution {
37 serializer.write_unsigned_integer(0u64)?;
38 let mut stake_distribution_inner_se = Serializer::new_vec();
39 self.stake_distribution
40 .as_ref()
41 .unwrap()
42 .serialize(&mut stake_distribution_inner_se)?;
43 let stake_distribution_bytes = stake_distribution_inner_se.finalize();
44 serializer.write_bytes(&stake_distribution_bytes)?;
45 }
46 if let Some(field) = &self.derivation_path {
47 serializer.write_unsigned_integer(1u64)?;
48 let mut derivation_path_inner_se = Serializer::new_vec();
49 field.serialize(&mut derivation_path_inner_se)?;
50 let derivation_path_bytes = derivation_path_inner_se.finalize();
51 serializer.write_bytes(&derivation_path_bytes)?;
52 }
53 if let Some(field) = &self.protocol_magic {
54 serializer.write_unsigned_integer(2u64)?;
55 let mut protocol_magic_inner_se = Serializer::new_vec();
56 field.serialize(&mut protocol_magic_inner_se)?;
57 let protocol_magic_bytes = protocol_magic_inner_se.finalize();
58 serializer.write_bytes(&protocol_magic_bytes)?;
59 }
60 Ok(serializer)
61 }
62}
63
64impl Deserialize for AddrAttributes {
65 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
66 let len = raw.map()?;
67 let mut read_len = CBORReadLen::from(len);
68 (|| -> Result<_, DeserializeError> {
69 let mut stake_distribution = None;
70 let mut derivation_path = None;
71 let mut protocol_magic = None;
72 let mut read = 0;
73 while match len {
74 cbor_event::Len::Len(n) => read < n,
75 cbor_event::Len::Indefinite => true,
76 } {
77 match raw.cbor_type()? {
78 cbor_event::Type::UnsignedInteger => match raw.unsigned_integer()? {
79 0 => {
80 if stake_distribution.is_some() {
81 return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into());
82 }
83 stake_distribution = Some(
84 (|| -> Result<_, DeserializeError> {
85 let stake_distribution_bytes = raw.bytes()?;
86 let inner_de = &mut Deserializer::from(std::io::Cursor::new(
87 stake_distribution_bytes,
88 ));
89 read_len.read_elems(1)?;
90 StakeDistribution::deserialize(inner_de)
91 })()
92 .map_err(|e| e.annotate("stake_distribution"))?,
93 );
94 }
95 1 => {
96 if derivation_path.is_some() {
97 return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into());
98 }
99 derivation_path = Some(
100 (|| -> Result<_, DeserializeError> {
101 let derivation_path_bytes = raw.bytes()?;
102 let inner_de = &mut Deserializer::from(std::io::Cursor::new(
103 derivation_path_bytes,
104 ));
105 read_len.read_elems(1)?;
106 HDAddressPayload::deserialize(inner_de)
107 })()
108 .map_err(|e| e.annotate("derivation_path"))?,
109 );
110 }
111 2 => {
112 if protocol_magic.is_some() {
113 return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into());
114 }
115 protocol_magic = Some(
116 (|| -> Result<_, DeserializeError> {
117 let protocol_magic_bytes = raw.bytes()?;
118 let inner_de = &mut Deserializer::from(std::io::Cursor::new(
119 protocol_magic_bytes,
120 ));
121 read_len.read_elems(1)?;
122 ProtocolMagic::deserialize(inner_de)
123 })()
124 .map_err(|e| e.annotate("protocol_magic"))?,
125 );
126 }
127 unknown_key => {
128 return Err(
129 DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into()
130 )
131 }
132 },
133 cbor_event::Type::Text => {
134 return Err(DeserializeFailure::UnknownKey(Key::Str(raw.text()?)).into())
135 }
136 cbor_event::Type::Special => match len {
137 cbor_event::Len::Len(_) => {
138 return Err(DeserializeFailure::BreakInDefiniteLen.into())
139 }
140 cbor_event::Len::Indefinite => match raw.special()? {
141 cbor_event::Special::Break => break,
142 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
143 },
144 },
145 other_type => {
146 return Err(DeserializeFailure::UnexpectedKeyType(other_type).into())
147 }
148 }
149 read += 1;
150 }
151 read_len.finish()?;
152 Ok(Self {
153 stake_distribution,
154 derivation_path,
155 protocol_magic,
156 })
157 })()
158 .map_err(|e| e.annotate("AddrAttributes"))
159 }
160}
161
162impl cbor_event::se::Serialize for AddressContent {
163 fn serialize<'se, W: Write>(
164 &self,
165 serializer: &'se mut Serializer<W>,
166 ) -> cbor_event::Result<&'se mut Serializer<W>> {
167 serializer.write_array(cbor_event::Len::Len(3))?;
168 serializer.write_bytes(self.address_id.to_raw_bytes())?;
169 self.addr_attributes.serialize(serializer)?;
170 match &self.addr_type {
171 ByronAddrType::PublicKey => serializer.write_unsigned_integer(0u64),
172 ByronAddrType::Script => serializer.write_unsigned_integer(1u64),
173 ByronAddrType::Redeem => serializer.write_unsigned_integer(2u64),
174 }?;
175 Ok(serializer)
176 }
177}
178
179impl Deserialize for AddressContent {
180 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
181 let len = raw.array()?;
182 let mut read_len = CBORReadLen::new(match len {
183 cbor_event::Len::Len(n) => LenSz::Len(n, fit_sz(n, None, true)),
184 cbor_event::Len::Indefinite => LenSz::Indefinite,
185 });
186 read_len.read_elems(3)?;
187 (|| -> Result<_, DeserializeError> {
188 let address_id = raw
189 .bytes()
190 .map_err(Into::<DeserializeError>::into)
191 .and_then(|bytes| {
192 AddressId::from_raw_bytes(&bytes)
193 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
194 })
195 .map_err(|e: DeserializeError| e.annotate("address_id"))?;
196 let addr_attributes = AddrAttributes::deserialize(raw)
197 .map_err(|e: DeserializeError| e.annotate("addr_attributes"))?;
198 let addr_type = (|| -> Result<_, DeserializeError> {
199 let initial_position = raw.as_mut_ref().stream_position().unwrap();
200 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
201 let public_key_value = raw.unsigned_integer()?;
202 if public_key_value != 0 {
203 return Err(DeserializeFailure::FixedValueMismatch {
204 found: Key::Uint(public_key_value),
205 expected: Key::Uint(0),
206 }
207 .into());
208 }
209 Ok(())
210 })(raw);
211 match deser_variant {
212 Ok(()) => return Ok(ByronAddrType::PublicKey),
213 Err(_) => raw
214 .as_mut_ref()
215 .seek(SeekFrom::Start(initial_position))
216 .unwrap(),
217 };
218 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
219 let script_value = raw.unsigned_integer()?;
220 if script_value != 1 {
221 return Err(DeserializeFailure::FixedValueMismatch {
222 found: Key::Uint(script_value),
223 expected: Key::Uint(1),
224 }
225 .into());
226 }
227 Ok(())
228 })(raw);
229 match deser_variant {
230 Ok(()) => return Ok(ByronAddrType::Script),
231 Err(_) => raw
232 .as_mut_ref()
233 .seek(SeekFrom::Start(initial_position))
234 .unwrap(),
235 };
236 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
237 let redeem_value = raw.unsigned_integer()?;
238 if redeem_value != 2 {
239 return Err(DeserializeFailure::FixedValueMismatch {
240 found: Key::Uint(redeem_value),
241 expected: Key::Uint(2),
242 }
243 .into());
244 }
245 Ok(())
246 })(raw);
247 match deser_variant {
248 Ok(()) => return Ok(ByronAddrType::Redeem),
249 Err(_) => raw
250 .as_mut_ref()
251 .seek(SeekFrom::Start(initial_position))
252 .unwrap(),
253 };
254 Err(DeserializeError::new(
255 "ByronAddrType",
256 DeserializeFailure::NoVariantMatched,
257 ))
258 })()
259 .map_err(|e| e.annotate("addr_type"))?;
260 match len {
261 cbor_event::Len::Len(_) => (),
262 cbor_event::Len::Indefinite => match raw.special()? {
263 cbor_event::Special::Break => (),
264 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
265 },
266 }
267 Ok(AddressContent {
268 address_id,
269 addr_attributes,
270 addr_type,
271 })
272 })()
273 .map_err(|e| e.annotate("AddressContent"))
274 }
275}
276
277impl cbor_event::se::Serialize for ByronAddress {
278 fn serialize<'se, W: Write>(
279 &self,
280 serializer: &'se mut Serializer<W>,
281 ) -> cbor_event::Result<&'se mut Serializer<W>> {
282 serializer.write_array(cbor_event::Len::Len(2))?;
283 serializer.write_tag(24u64)?;
284 let mut content_inner_se = Serializer::new_vec();
285 self.content.serialize(&mut content_inner_se)?;
286 let content_bytes = content_inner_se.finalize();
287 serializer.write_bytes(&content_bytes)?;
288 self.crc.serialize(serializer)?;
289 Ok(serializer)
290 }
291}
292
293impl Deserialize for ByronAddress {
294 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
295 let len = raw.array()?;
296 let mut read_len = CBORReadLen::from(len);
297 read_len.read_elems(2)?;
298 (|| -> Result<_, DeserializeError> {
299 let (content, content_crc) = (|| -> Result<_, DeserializeError> {
300 match raw.tag()? {
301 24 => {
302 let content_bytes = raw.bytes()?;
303 let crc = crate::byron::crc32::crc32(&content_bytes);
304 let inner_de = &mut Deserializer::from(std::io::Cursor::new(content_bytes));
305 Ok((AddressContent::deserialize(inner_de)?, crc))
306 }
307 tag => Err(DeserializeFailure::TagMismatch {
308 found: tag,
309 expected: 24,
310 }
311 .into()),
312 }
313 })()
314 .map_err(|e| e.annotate("content"))?;
315 let crc = Crc32::deserialize(raw).map_err(|e: DeserializeError| e.annotate("crc"))?;
316 if Into::<u32>::into(crc) != content_crc {
317 return Err(DeserializeFailure::InvalidStructure(Box::new(
318 ByronAddressError::InvalidCRC {
319 found: crc,
320 expected: content_crc.into(),
321 },
322 ))
323 .into());
324 }
325 match len {
326 cbor_event::Len::Len(_) => (),
327 cbor_event::Len::Indefinite => match raw.special()? {
328 cbor_event::Special::Break => (),
329 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
330 },
331 }
332 Ok(ByronAddress { content, crc })
333 })()
334 .map_err(|e| e.annotate("ByronAddress"))
335 }
336}
337
338impl cbor_event::se::Serialize for ByronTxOut {
339 fn serialize<'se, W: Write>(
340 &self,
341 serializer: &'se mut Serializer<W>,
342 ) -> cbor_event::Result<&'se mut Serializer<W>> {
343 serializer.write_array(cbor_event::Len::Len(2))?;
344 self.address.serialize(serializer)?;
345 serializer.write_unsigned_integer(self.amount)?;
346 Ok(serializer)
347 }
348}
349
350impl Deserialize for ByronTxOut {
351 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
352 let len = raw.array()?;
353 let mut read_len = CBORReadLen::from(len);
354 read_len.read_elems(2)?;
355 (|| -> Result<_, DeserializeError> {
356 let address = ByronAddress::deserialize(raw)
357 .map_err(|e: DeserializeError| e.annotate("address"))?;
358 let amount =
359 Ok(raw.unsigned_integer()?).map_err(|e: DeserializeError| e.annotate("amount"))?;
360 match len {
361 cbor_event::Len::Len(_) => (),
362 cbor_event::Len::Indefinite => match raw.special()? {
363 cbor_event::Special::Break => (),
364 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
365 },
366 }
367 Ok(ByronTxOut { address, amount })
368 })()
369 .map_err(|e| e.annotate("ByronTxOut"))
370 }
371}
372
373impl cbor_event::se::Serialize for HDAddressPayload {
374 fn serialize<'se, W: Write>(
375 &self,
376 serializer: &'se mut Serializer<W>,
377 ) -> cbor_event::Result<&'se mut Serializer<W>> {
378 serializer.write_bytes(&self.0)
379 }
380}
381
382impl Deserialize for HDAddressPayload {
383 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
384 Ok(Self(raw.bytes()? as Vec<u8>))
385 }
386}
387
388impl cbor_event::se::Serialize for SpendingData {
389 fn serialize<'se, W: Write>(
390 &self,
391 serializer: &'se mut Serializer<W>,
392 ) -> cbor_event::Result<&'se mut Serializer<W>> {
393 match self {
394 SpendingData::SpendingDataPubKey(pubkey) => {
395 serializer.write_array(cbor_event::Len::Len(2))?;
396 serializer.write_unsigned_integer(0u64)?;
397 serializer.write_bytes(pubkey.to_raw_bytes())?;
398 Ok(serializer)
399 }
400 SpendingData::SpendingDataScript(script) => {
401 serializer.write_array(cbor_event::Len::Len(2))?;
402 serializer.write_unsigned_integer(1u64)?;
403 serializer.write_bytes(script.to_raw_bytes())?;
404 Ok(serializer)
405 }
406 SpendingData::SpendingDataRedeem(redeem) => {
407 serializer.write_array(cbor_event::Len::Len(2))?;
408 serializer.write_unsigned_integer(2u64)?;
409 serializer.write_bytes(redeem.to_raw_bytes())?;
410 Ok(serializer)
411 }
412 }
413 }
414}
415
416impl Deserialize for SpendingData {
417 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
418 (|| -> Result<_, DeserializeError> {
419 let len = raw.array()?;
420 let _read_len = CBORReadLen::from(len);
421 let initial_position = raw.as_mut_ref().stream_position().unwrap();
422 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
423 (|| -> Result<_, DeserializeError> {
424 let tag_value = raw.unsigned_integer()?;
425 if tag_value != 0 {
426 return Err(DeserializeFailure::FixedValueMismatch {
427 found: Key::Uint(tag_value),
428 expected: Key::Uint(0),
429 }
430 .into());
431 }
432 Ok(())
433 })()
434 .map_err(|e| e.annotate("tag"))?;
435 let pubkey = raw
436 .bytes()
437 .map_err(Into::<DeserializeError>::into)
438 .and_then(|bytes| {
439 Bip32PublicKey::from_raw_bytes(&bytes)
440 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
441 })
442 .map_err(|e: DeserializeError| e.annotate("pubkey"))?;
443 match len {
444 cbor_event::Len::Len(_) => (),
445 cbor_event::Len::Indefinite => match raw.special()? {
446 cbor_event::Special::Break => (),
447 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
448 },
449 }
450 Ok(Self::SpendingDataPubKey(pubkey))
451 })(raw);
452 match deser_variant {
453 Ok(variant) => return Ok(variant),
454 Err(_) => raw
455 .as_mut_ref()
456 .seek(SeekFrom::Start(initial_position))
457 .unwrap(),
458 };
459 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
460 (|| -> Result<_, DeserializeError> {
461 let tag_value = raw.unsigned_integer()?;
462 if tag_value != 1 {
463 return Err(DeserializeFailure::FixedValueMismatch {
464 found: Key::Uint(tag_value),
465 expected: Key::Uint(1),
466 }
467 .into());
468 }
469 Ok(())
470 })()
471 .map_err(|e| e.annotate("tag"))?;
472 let script = raw
473 .bytes()
474 .map_err(Into::<DeserializeError>::into)
475 .and_then(|bytes| {
476 ByronScript::from_raw_bytes(&bytes)
477 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
478 })
479 .map_err(|e: DeserializeError| e.annotate("script"))?;
480 match len {
481 cbor_event::Len::Len(_) => (),
482 cbor_event::Len::Indefinite => match raw.special()? {
483 cbor_event::Special::Break => (),
484 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
485 },
486 }
487 Ok(Self::SpendingDataScript(script))
488 })(raw);
489 match deser_variant {
490 Ok(variant) => return Ok(variant),
491 Err(_) => raw
492 .as_mut_ref()
493 .seek(SeekFrom::Start(initial_position))
494 .unwrap(),
495 };
496 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
497 (|| -> Result<_, DeserializeError> {
498 let tag_value = raw.unsigned_integer()?;
499 if tag_value != 2 {
500 return Err(DeserializeFailure::FixedValueMismatch {
501 found: Key::Uint(tag_value),
502 expected: Key::Uint(2),
503 }
504 .into());
505 }
506 Ok(())
507 })()
508 .map_err(|e| e.annotate("tag"))?;
509 let redeem = raw
510 .bytes()
511 .map_err(Into::<DeserializeError>::into)
512 .and_then(|bytes| {
513 PublicKey::from_raw_bytes(&bytes)
514 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
515 })
516 .map_err(|e: DeserializeError| e.annotate("redeem"))?;
517 match len {
518 cbor_event::Len::Len(_) => (),
519 cbor_event::Len::Indefinite => match raw.special()? {
520 cbor_event::Special::Break => (),
521 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
522 },
523 }
524 Ok(Self::SpendingDataRedeem(redeem))
525 })(raw);
526 match deser_variant {
527 Ok(variant) => return Ok(variant),
528 Err(_) => raw
529 .as_mut_ref()
530 .seek(SeekFrom::Start(initial_position))
531 .unwrap(),
532 };
533 match len {
534 cbor_event::Len::Len(_) => (),
535 cbor_event::Len::Indefinite => match raw.special()? {
536 cbor_event::Special::Break => (),
537 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
538 },
539 }
540 Err(DeserializeError::new(
541 "SpendingData",
542 DeserializeFailure::NoVariantMatched,
543 ))
544 })()
545 .map_err(|e| e.annotate("SpendingData"))
546 }
547}
548
549impl cbor_event::se::Serialize for StakeDistribution {
550 fn serialize<'se, W: Write>(
551 &self,
552 serializer: &'se mut Serializer<W>,
553 ) -> cbor_event::Result<&'se mut Serializer<W>> {
554 match self {
555 StakeDistribution::SingleKey(stakeholder_id) => {
556 serializer.write_array(cbor_event::Len::Len(2))?;
557 serializer.write_unsigned_integer(0u64)?;
558 serializer.write_bytes(stakeholder_id.to_raw_bytes())?;
559 Ok(serializer)
560 }
561 StakeDistribution::BootstrapEra => {
562 serializer.write_array(cbor_event::Len::Len(1))?;
563 serializer.write_unsigned_integer(1u64)
564 }
565 }
566 }
567}
568
569impl Deserialize for StakeDistribution {
570 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
571 (|| -> Result<_, DeserializeError> {
572 let len = raw.array()?;
573 let _read_len = CBORReadLen::from(len);
574 let initial_position = raw.as_mut_ref().stream_position().unwrap();
575 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
576 (|| -> Result<_, DeserializeError> {
577 let tag_value = raw.unsigned_integer()?;
578 if tag_value != 0 {
579 return Err(DeserializeFailure::FixedValueMismatch {
580 found: Key::Uint(tag_value),
581 expected: Key::Uint(0),
582 }
583 .into());
584 }
585 Ok(())
586 })()
587 .map_err(|e| e.annotate("tag"))?;
588 let stakeholder_id = raw
589 .bytes()
590 .map_err(Into::<DeserializeError>::into)
591 .and_then(|bytes| {
592 StakeholderId::from_raw_bytes(&bytes)
593 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
594 })
595 .map_err(|e: DeserializeError| e.annotate("stakeholder_id"))?;
596 match len {
597 cbor_event::Len::Len(_) => (),
598 cbor_event::Len::Indefinite => match raw.special()? {
599 cbor_event::Special::Break => (),
600 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
601 },
602 }
603 Ok(Self::SingleKey(stakeholder_id))
604 })(raw);
605 match deser_variant {
606 Ok(variant) => return Ok(variant),
607 Err(_) => raw
608 .as_mut_ref()
609 .seek(SeekFrom::Start(initial_position))
610 .unwrap(),
611 };
612 let deser_variant = (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
613 let bootstrap_era_distr_value = raw.unsigned_integer()?;
614 if bootstrap_era_distr_value != 1 {
615 return Err(DeserializeFailure::FixedValueMismatch {
616 found: Key::Uint(bootstrap_era_distr_value),
617 expected: Key::Uint(1),
618 }
619 .into());
620 }
621 Ok(())
622 })(raw);
623 match deser_variant {
624 Ok(()) => return Ok(StakeDistribution::BootstrapEra),
625 Err(_) => raw
626 .as_mut_ref()
627 .seek(SeekFrom::Start(initial_position))
628 .unwrap(),
629 };
630 match len {
631 cbor_event::Len::Len(_) => (),
632 cbor_event::Len::Indefinite => match raw.special()? {
633 cbor_event::Special::Break => (),
634 _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
635 },
636 }
637 Err(DeserializeError::new(
638 "StakeDistribution",
639 DeserializeFailure::NoVariantMatched,
640 ))
641 })()
642 .map_err(|e| e.annotate("StakeDistribution"))
643 }
644}