miden_tx/errors/
mod.rs

1use alloc::{boxed::Box, string::String};
2use core::error::Error;
3
4use miden_objects::{
5    AccountError, Felt, ProvenTransactionError, TransactionInputError, TransactionOutputError,
6    account::AccountId, block::BlockNumber, note::NoteId,
7};
8use miden_verifier::VerificationError;
9use thiserror::Error;
10use vm_processor::ExecutionError;
11
12// TRANSACTION EXECUTOR ERROR
13// ================================================================================================
14
15#[derive(Debug, Error)]
16pub enum TransactionExecutorError {
17    #[error("failed to execute transaction kernel program")]
18    TransactionProgramExecutionFailed(#[source] ExecutionError),
19    #[error("failed to fetch transaction inputs from the data store")]
20    FetchTransactionInputsFailed(#[source] DataStoreError),
21    #[error("input account ID {input_id} does not match output account ID {output_id}")]
22    InconsistentAccountId {
23        input_id: AccountId,
24        output_id: AccountId,
25    },
26    #[error("expected account nonce {expected:?}, found {actual:?}")]
27    InconsistentAccountNonceDelta {
28        expected: Option<Felt>,
29        actual: Option<Felt>,
30    },
31    #[error("failed to construct transaction outputs")]
32    TransactionOutputConstructionFailed(#[source] TransactionOutputError),
33    #[error("failed to create transaction host")]
34    TransactionHostCreationFailed(#[source] TransactionHostError),
35}
36
37// TRANSACTION PROVER ERROR
38// ================================================================================================
39
40#[derive(Debug, Error)]
41pub enum TransactionProverError {
42    #[error("failed to apply account delta")]
43    AccountDeltaApplyFailed(#[source] AccountError),
44    #[error("failed to construct transaction outputs")]
45    TransactionOutputConstructionFailed(#[source] TransactionOutputError),
46    #[error("failed to build proven transaction")]
47    ProvenTransactionBuildFailed(#[source] ProvenTransactionError),
48    #[error("failed to execute transaction kernel program")]
49    TransactionProgramExecutionFailed(#[source] ExecutionError),
50    #[error("failed to create transaction host")]
51    TransactionHostCreationFailed(#[source] TransactionHostError),
52    /// Custom error variant for errors not covered by the other variants.
53    #[error("{error_msg}")]
54    Other {
55        error_msg: Box<str>,
56        // thiserror will return this when calling Error::source on DataStoreError.
57        source: Option<Box<dyn Error + Send + Sync + 'static>>,
58    },
59}
60
61impl TransactionProverError {
62    /// Creates a custom error using the [`TransactionProverError::Other`] variant from an error
63    /// message.
64    pub fn other(message: impl Into<String>) -> Self {
65        let message: String = message.into();
66        Self::Other { error_msg: message.into(), source: None }
67    }
68
69    /// Creates a custom error using the [`TransactionProverError::Other`] variant from an error
70    /// message and a source error.
71    pub fn other_with_source(
72        message: impl Into<String>,
73        source: impl Error + Send + Sync + 'static,
74    ) -> Self {
75        let message: String = message.into();
76        Self::Other {
77            error_msg: message.into(),
78            source: Some(Box::new(source)),
79        }
80    }
81}
82
83// TRANSACTION VERIFIER ERROR
84// ================================================================================================
85
86#[derive(Debug, Error)]
87pub enum TransactionVerifierError {
88    #[error("failed to verify transaction")]
89    TransactionVerificationFailed(#[source] VerificationError),
90    #[error("transaction proof security level is {actual} but must be at least {expected_minimum}")]
91    InsufficientProofSecurityLevel { actual: u32, expected_minimum: u32 },
92}
93
94// TRANSACTION HOST ERROR
95// ================================================================================================
96
97#[derive(Debug, Error)]
98pub enum TransactionHostError {
99    #[error("{0}")]
100    AccountProcedureIndexMapError(String),
101    #[error("failed to create account procedure info")]
102    AccountProcedureInfoCreationFailed(#[source] AccountError),
103}
104
105// DATA STORE ERROR
106// ================================================================================================
107
108#[derive(Debug, Error)]
109pub enum DataStoreError {
110    #[error("account with id {0} not found in data store")]
111    AccountNotFound(AccountId),
112    #[error("block with number {0} not found in data store")]
113    BlockNotFound(BlockNumber),
114    #[error("failed to create transaction inputs")]
115    InvalidTransactionInput(#[source] TransactionInputError),
116    #[error("note with id {0} is already consumed")]
117    NoteAlreadyConsumed(NoteId),
118    #[error("not with id {0} not found in data store")]
119    NoteNotFound(NoteId),
120    /// Custom error variant for implementors of the [`DataStore`](crate::executor::DataStore)
121    /// trait.
122    #[error("{error_msg}")]
123    Other {
124        error_msg: Box<str>,
125        // thiserror will return this when calling Error::source on DataStoreError.
126        source: Option<Box<dyn Error + Send + Sync + 'static>>,
127    },
128}
129
130impl DataStoreError {
131    /// Creates a custom error using the [`DataStoreError::Other`] variant from an error message.
132    pub fn other(message: impl Into<String>) -> Self {
133        let message: String = message.into();
134        Self::Other { error_msg: message.into(), source: None }
135    }
136
137    /// Creates a custom error using the [`DataStoreError::Other`] variant from an error message and
138    /// a source error.
139    pub fn other_with_source(
140        message: impl Into<String>,
141        source: impl Error + Send + Sync + 'static,
142    ) -> Self {
143        let message: String = message.into();
144        Self::Other {
145            error_msg: message.into(),
146            source: Some(Box::new(source)),
147        }
148    }
149}
150
151// AUTHENTICATION ERROR
152// ================================================================================================
153
154#[derive(Debug, Error)]
155pub enum AuthenticationError {
156    #[error("signature rejected: {0}")]
157    RejectedSignature(String),
158    #[error("unknown public key: {0}")]
159    UnknownPublicKey(String),
160    /// Custom error variant for implementors of the
161    /// [`TransactionAuthenticatior`](crate::auth::TransactionAuthenticator) trait.
162    #[error("{error_msg}")]
163    Other {
164        error_msg: Box<str>,
165        // thiserror will return this when calling Error::source on DataStoreError.
166        source: Option<Box<dyn Error + Send + Sync + 'static>>,
167    },
168}
169
170impl AuthenticationError {
171    /// Creates a custom error using the [`AuthenticationError::Other`] variant from an error
172    /// message.
173    pub fn other(message: impl Into<String>) -> Self {
174        let message: String = message.into();
175        Self::Other { error_msg: message.into(), source: None }
176    }
177
178    /// Creates a custom error using the [`AuthenticationError::Other`] variant from an error
179    /// message and a source error.
180    pub fn other_with_source(
181        message: impl Into<String>,
182        source: impl Error + Send + Sync + 'static,
183    ) -> Self {
184        let message: String = message.into();
185        Self::Other {
186            error_msg: message.into(),
187            source: Some(Box::new(source)),
188        }
189    }
190}
191
192#[cfg(test)]
193mod error_assertions {
194    use super::*;
195
196    /// Asserts at compile time that the passed error has Send + Sync + 'static bounds.
197    fn _assert_error_is_send_sync_static<E: core::error::Error + Send + Sync + 'static>(_: E) {}
198
199    fn _assert_data_store_error_bounds(err: DataStoreError) {
200        _assert_error_is_send_sync_static(err);
201    }
202
203    fn _assert_authentication_error_bounds(err: AuthenticationError) {
204        _assert_error_is_send_sync_static(err);
205    }
206}