Skip to main content

nym_credentials/ecash/bandwidth/
importable.rs

1// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::ecash::bandwidth::serialiser::keys::EpochVerificationKey;
5use crate::ecash::bandwidth::serialiser::signatures::{
6    AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures,
7};
8use crate::ecash::bandwidth::{
9    issued::IssuedTicketBook,
10    serialiser::{VersionSerialised, VersionedSerialise},
11};
12use crate::Error;
13use serde::de::DeserializeOwned;
14use serde::{Deserialize, Serialize};
15use zeroize::{Zeroize, ZeroizeOnDrop};
16
17pub struct DecodedImportableTicketBook {
18    pub ticketbook: IssuedTicketBook,
19
20    pub expiration_date_signatures: Option<AggregatedExpirationDateSignatures>,
21
22    pub coin_index_signatures: Option<AggregatedCoinIndicesSignatures>,
23
24    pub master_verification_key: Option<EpochVerificationKey>,
25}
26
27#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
28pub struct ImportableTicketBook {
29    pub serialised_ticketbook: VersionSerialised<IssuedTicketBook>,
30
31    #[zeroize(skip)]
32    pub serialised_expiration_date_signatures:
33        Option<VersionSerialised<AggregatedExpirationDateSignatures>>,
34
35    #[zeroize(skip)]
36    pub serialised_coin_index_signatures:
37        Option<VersionSerialised<AggregatedCoinIndicesSignatures>>,
38
39    #[zeroize(skip)]
40    pub serialised_master_verification_key: Option<VersionSerialised<EpochVerificationKey>>,
41}
42
43impl From<IssuedTicketBook> for ImportableTicketBook {
44    fn from(ticketbook: IssuedTicketBook) -> Self {
45        ImportableTicketBook {
46            serialised_ticketbook: ticketbook.pack(),
47            serialised_expiration_date_signatures: None,
48            serialised_coin_index_signatures: None,
49            serialised_master_verification_key: None,
50        }
51    }
52}
53
54impl ImportableTicketBook {
55    pub fn with_expiration_date_signatures(
56        mut self,
57        signatures: &AggregatedExpirationDateSignatures,
58    ) -> Self {
59        self.serialised_expiration_date_signatures = Some(signatures.pack());
60        self
61    }
62
63    pub fn with_coin_index_signatures(
64        mut self,
65        signatures: &AggregatedCoinIndicesSignatures,
66    ) -> Self {
67        self.serialised_coin_index_signatures = Some(signatures.pack());
68        self
69    }
70
71    pub fn with_master_verification_key(mut self, key: &EpochVerificationKey) -> Self {
72        self.serialised_master_verification_key = Some(key.pack());
73        self
74    }
75
76    pub fn with_maybe_expiration_date_signatures(
77        self,
78        signatures: &Option<AggregatedExpirationDateSignatures>,
79    ) -> Self {
80        if let Some(sigs) = signatures {
81            self.with_expiration_date_signatures(sigs)
82        } else {
83            self
84        }
85    }
86
87    pub fn with_maybe_coin_index_signatures(
88        self,
89        signatures: &Option<AggregatedCoinIndicesSignatures>,
90    ) -> Self {
91        if let Some(sigs) = signatures {
92            self.with_coin_index_signatures(sigs)
93        } else {
94            self
95        }
96    }
97
98    pub fn with_maybe_master_verification_key(self, key: &Option<EpochVerificationKey>) -> Self {
99        if let Some(sigs) = key {
100            self.with_master_verification_key(sigs)
101        } else {
102            self
103        }
104    }
105
106    pub fn finalize_export(self) -> VersionSerialised<Self> {
107        self.pack()
108    }
109
110    pub fn try_unpack_full(&self) -> Result<DecodedImportableTicketBook, Error> {
111        Ok(DecodedImportableTicketBook {
112            ticketbook: self.serialised_ticketbook.try_unpack()?,
113            expiration_date_signatures: self
114                .serialised_expiration_date_signatures
115                .as_ref()
116                .map(|sigs| sigs.try_unpack())
117                .transpose()?,
118            coin_index_signatures: self
119                .serialised_coin_index_signatures
120                .as_ref()
121                .map(|sigs| sigs.try_unpack())
122                .transpose()?,
123            master_verification_key: self
124                .serialised_master_verification_key
125                .as_ref()
126                .map(|key| key.try_unpack())
127                .transpose()?,
128        })
129    }
130}
131
132impl VersionedSerialise for ImportableTicketBook {
133    const CURRENT_SERIALISATION_REVISION: u8 = 1;
134
135    fn try_unpack(b: &[u8], revision: impl Into<Option<u8>>) -> Result<Self, Error>
136    where
137        Self: DeserializeOwned,
138    {
139        let revision = revision
140            .into()
141            .unwrap_or(<Self as VersionedSerialise>::CURRENT_SERIALISATION_REVISION);
142
143        match revision {
144            1 => Self::try_unpack_current(b),
145            _ => Err(Error::UnknownSerializationRevision { revision }),
146        }
147    }
148}