nrc_mls/
error.rs

1// Copyright (c) 2024-2025 Jeff Gardner
2// Copyright (c) 2025 Rust Nostr Developers
3// Distributed under the MIT software license
4
5//! Nostr MLS errors
6
7use std::string::FromUtf8Error;
8use std::{fmt, str};
9
10use nostr::nips::nip44;
11use nostr::types::url;
12use nostr::{event, key, Kind, SignerError};
13use openmls::credentials::errors::BasicCredentialError;
14use openmls::error::LibraryError;
15use openmls::extensions::errors::InvalidExtensionError;
16use openmls::framing::errors::ProtocolMessageError;
17use openmls::group::{
18    AddMembersError, CommitToPendingProposalsError, CreateGroupContextExtProposalError,
19    CreateMessageError, ExportSecretError, MergePendingCommitError, NewGroupError,
20    ProcessMessageError, SelfUpdateError, WelcomeError,
21};
22use openmls::key_packages::errors::{KeyPackageNewError, KeyPackageVerifyError};
23use openmls_traits::types::CryptoError;
24
25/// Nostr MLS error
26#[derive(Debug, PartialEq)]
27pub enum Error {
28    /// Hex error
29    Hex(hex::FromHexError),
30    /// Keys error
31    Keys(key::Error),
32    /// Event error
33    Event(event::Error),
34    /// Event Builder error
35    EventBuilder(event::builder::Error),
36    /// Nostr Signer error
37    Signer(SignerError),
38    /// NIP44 error
39    NIP44(nip44::Error),
40    /// Relay URL error
41    RelayUrl(url::Error),
42    /// TLS error
43    Tls(tls_codec::Error),
44    /// UTF8 error
45    Utf8(str::Utf8Error),
46    /// Crypto error
47    Crypto(CryptoError),
48    /// Generic OpenMLS error
49    OpenMlsGeneric(LibraryError),
50    /// Invalid extension error
51    InvalidExtension(InvalidExtensionError),
52    /// Create message error
53    CreateMessage(CreateMessageError),
54    /// Export secret error
55    ExportSecret(ExportSecretError),
56    /// Basic credential error
57    BasicCredential(BasicCredentialError),
58    /// Process message error
59    ProcessMessage(ProcessMessageError),
60    /// Protocol message error
61    ProtocolMessage(String),
62    /// Key package error
63    KeyPackage(String),
64    /// Group error
65    Group(String),
66    /// Group exporter secret not found
67    GroupExporterSecretNotFound,
68    /// Message error
69    Message(String),
70    /// Cannot decrypt own message
71    CannotDecryptOwnMessage,
72    /// Merge pending commit error
73    MergePendingCommit(String),
74    /// Commit to pending proposal
75    CommitToPendingProposalsError,
76    /// Self update error
77    SelfUpdate(String),
78    /// Welcome error
79    Welcome(String),
80    /// We're missing a Welcome for an existing ProcessedWelcome
81    MissingWelcomeForProcessedWelcome,
82    /// Processed welcome not found
83    ProcessedWelcomeNotFound,
84    /// Provider error
85    Provider(String),
86    /// Group not found
87    GroupNotFound,
88    /// Protocol message group ID doesn't match the current group ID
89    ProtocolGroupIdMismatch,
90    /// Own leaf not found
91    OwnLeafNotFound,
92    /// Failed to load signer
93    CantLoadSigner,
94    /// Invalid Welcome message
95    InvalidWelcomeMessage,
96    /// Unexpected event
97    UnexpectedEvent {
98        /// Expected event kind
99        expected: Kind,
100        /// Received event kind
101        received: Kind,
102    },
103    /// Unexpected extension type
104    UnexpectedExtensionType,
105    /// Nostr group data extension not found
106    NostrGroupDataExtensionNotFound,
107    /// Message from a non-member of a group
108    MessageFromNonMember,
109    /// Code path is not yet implemented
110    NotImplemented(String),
111    /// Stored message not found
112    MessageNotFound,
113    /// Proposal message received from a non-admin
114    ProposalFromNonAdmin,
115    /// Commit message received from a non-admin
116    CommitFromNonAdmin,
117    /// Error when updating group context extensions
118    UpdateGroupContextExts(String),
119}
120
121impl std::error::Error for Error {}
122
123impl fmt::Display for Error {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        match self {
126            Self::Hex(e) => write!(f, "{e}"),
127            Self::Keys(e) => write!(f, "{e}"),
128            Self::Event(e) => write!(f, "{e}"),
129            Self::EventBuilder(e) => write!(f, "{e}"),
130            Self::Signer(e) => write!(f, "{e}"),
131            Self::NIP44(e) => write!(f, "{e}"),
132            Self::RelayUrl(e) => write!(f, "{e}"),
133            Self::Tls(e) => write!(f, "{e}"),
134            Self::Utf8(e) => write!(f, "{e}"),
135            Self::Crypto(e) => write!(f, "{e}"),
136            Self::OpenMlsGeneric(e) => write!(f, "{e}"),
137            Self::InvalidExtension(e) => write!(f, "{e}"),
138            Self::CreateMessage(e) => write!(f, "{e}"),
139            Self::ExportSecret(e) => write!(f, "{e}"),
140            Self::BasicCredential(e) => write!(f, "{e}"),
141            Self::ProcessMessage(e) => write!(f, "{e}"),
142            Self::ProtocolMessage(e) => write!(f, "{e}"),
143            Self::KeyPackage(e) => write!(f, "{e}"),
144            Self::Group(e) => write!(f, "{e}"),
145            Self::GroupExporterSecretNotFound => write!(f, "group exporter secret not found"),
146            Self::Message(e) => write!(f, "{e}"),
147            Self::CannotDecryptOwnMessage => write!(f, "cannot decrypt own message"),
148            Self::Welcome(e) => write!(f, "{e}"),
149            Self::MissingWelcomeForProcessedWelcome => {
150                write!(f, "missing welcome for processed welcome")
151            }
152            Self::ProcessedWelcomeNotFound => write!(f, "processed welcome not found"),
153            Self::MergePendingCommit(e) => write!(f, "{e}"),
154            Self::CommitToPendingProposalsError => {
155                write!(f, "unable to commit to pending proposal")
156            }
157            Self::SelfUpdate(e) => write!(f, "{e}"),
158            Self::Provider(e) => write!(f, "{e}"),
159            Self::GroupNotFound => write!(f, "group not found"),
160            Self::ProtocolGroupIdMismatch => write!(
161                f,
162                "protocol message group ID doesn't match the current group ID"
163            ),
164            Self::OwnLeafNotFound => write!(f, "own leaf not found"),
165            Self::CantLoadSigner => write!(f, "can't load signer"),
166            Self::InvalidWelcomeMessage => write!(f, "invalid welcome message"),
167            Self::UnexpectedEvent { expected, received } => write!(
168                f,
169                "unexpected event kind: expected={expected}, received={received}"
170            ),
171            Self::UnexpectedExtensionType => {
172                write!(f, "Unexpected extension type")
173            }
174            Self::NostrGroupDataExtensionNotFound => {
175                write!(f, "Nostr group data extension not found")
176            }
177            Self::MessageFromNonMember => {
178                write!(f, "Message recieved from non-member")
179            }
180            Self::NotImplemented(e) => {
181                write!(f, "{e}")
182            }
183            Self::MessageNotFound => write!(f, "stored message not found"),
184            Self::ProposalFromNonAdmin => write!(f, "not processing proposal from non-admin"),
185            Self::CommitFromNonAdmin => write!(f, "not processing commit from non-admin"),
186            Self::UpdateGroupContextExts(e) => {
187                write!(f, "Error when updating group context extensions {e}")
188            }
189        }
190    }
191}
192
193impl From<hex::FromHexError> for Error {
194    fn from(e: hex::FromHexError) -> Self {
195        Self::Hex(e)
196    }
197}
198
199impl From<key::Error> for Error {
200    fn from(e: key::Error) -> Self {
201        Self::Keys(e)
202    }
203}
204
205impl From<event::Error> for Error {
206    fn from(e: event::Error) -> Self {
207        Self::Event(e)
208    }
209}
210
211impl From<event::builder::Error> for Error {
212    fn from(e: event::builder::Error) -> Self {
213        Self::EventBuilder(e)
214    }
215}
216
217impl From<SignerError> for Error {
218    fn from(e: SignerError) -> Self {
219        Self::Signer(e)
220    }
221}
222
223impl From<nip44::Error> for Error {
224    fn from(e: nip44::Error) -> Self {
225        Self::NIP44(e)
226    }
227}
228
229impl From<url::Error> for Error {
230    fn from(e: url::Error) -> Self {
231        Self::RelayUrl(e)
232    }
233}
234
235impl From<tls_codec::Error> for Error {
236    fn from(e: tls_codec::Error) -> Self {
237        Self::Tls(e)
238    }
239}
240
241impl From<str::Utf8Error> for Error {
242    fn from(e: str::Utf8Error) -> Self {
243        Self::Utf8(e)
244    }
245}
246
247impl From<FromUtf8Error> for Error {
248    fn from(e: FromUtf8Error) -> Self {
249        Self::Utf8(e.utf8_error())
250    }
251}
252
253impl From<CryptoError> for Error {
254    fn from(e: CryptoError) -> Self {
255        Self::Crypto(e)
256    }
257}
258
259impl From<LibraryError> for Error {
260    fn from(e: LibraryError) -> Self {
261        Self::OpenMlsGeneric(e)
262    }
263}
264
265impl From<InvalidExtensionError> for Error {
266    fn from(e: InvalidExtensionError) -> Self {
267        Self::InvalidExtension(e)
268    }
269}
270
271impl From<CreateMessageError> for Error {
272    fn from(e: CreateMessageError) -> Self {
273        Self::CreateMessage(e)
274    }
275}
276
277impl From<ExportSecretError> for Error {
278    fn from(e: ExportSecretError) -> Self {
279        Self::ExportSecret(e)
280    }
281}
282
283impl From<BasicCredentialError> for Error {
284    fn from(e: BasicCredentialError) -> Self {
285        Self::BasicCredential(e)
286    }
287}
288
289impl From<ProcessMessageError> for Error {
290    fn from(e: ProcessMessageError) -> Self {
291        Self::ProcessMessage(e)
292    }
293}
294
295impl From<ProtocolMessageError> for Error {
296    fn from(e: ProtocolMessageError) -> Self {
297        Self::ProtocolMessage(e.to_string())
298    }
299}
300
301impl From<KeyPackageNewError> for Error {
302    fn from(e: KeyPackageNewError) -> Self {
303        Self::KeyPackage(e.to_string())
304    }
305}
306
307impl From<KeyPackageVerifyError> for Error {
308    fn from(e: KeyPackageVerifyError) -> Self {
309        Self::KeyPackage(e.to_string())
310    }
311}
312
313impl<T> From<NewGroupError<T>> for Error
314where
315    T: fmt::Display,
316{
317    fn from(e: NewGroupError<T>) -> Self {
318        Self::Group(e.to_string())
319    }
320}
321
322impl<T> From<AddMembersError<T>> for Error
323where
324    T: fmt::Display,
325{
326    fn from(e: AddMembersError<T>) -> Self {
327        Self::Group(e.to_string())
328    }
329}
330
331impl<T> From<MergePendingCommitError<T>> for Error
332where
333    T: fmt::Display,
334{
335    fn from(e: MergePendingCommitError<T>) -> Self {
336        Self::MergePendingCommit(e.to_string())
337    }
338}
339
340impl<T> From<CommitToPendingProposalsError<T>> for Error
341where
342    T: fmt::Display,
343{
344    fn from(_e: CommitToPendingProposalsError<T>) -> Self {
345        Self::CommitToPendingProposalsError
346    }
347}
348
349impl<T> From<SelfUpdateError<T>> for Error
350where
351    T: fmt::Display,
352{
353    fn from(e: SelfUpdateError<T>) -> Self {
354        Self::SelfUpdate(e.to_string())
355    }
356}
357
358impl<T> From<WelcomeError<T>> for Error
359where
360    T: fmt::Display,
361{
362    fn from(e: WelcomeError<T>) -> Self {
363        Self::Welcome(e.to_string())
364    }
365}
366
367impl<T> From<CreateGroupContextExtProposalError<T>> for Error
368where
369    T: fmt::Display,
370{
371    fn from(e: CreateGroupContextExtProposalError<T>) -> Self {
372        Self::UpdateGroupContextExts(e.to_string())
373    }
374}