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#[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#[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 #[error("{error_msg}")]
54 Other {
55 error_msg: Box<str>,
56 source: Option<Box<dyn Error + Send + Sync + 'static>>,
58 },
59}
60
61impl TransactionProverError {
62 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 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#[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#[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#[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 #[error("{error_msg}")]
123 Other {
124 error_msg: Box<str>,
125 source: Option<Box<dyn Error + Send + Sync + 'static>>,
127 },
128}
129
130impl DataStoreError {
131 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 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#[derive(Debug, Error)]
155pub enum AuthenticationError {
156 #[error("signature rejected: {0}")]
157 RejectedSignature(String),
158 #[error("unknown public key: {0}")]
159 UnknownPublicKey(String),
160 #[error("{error_msg}")]
163 Other {
164 error_msg: Box<str>,
165 source: Option<Box<dyn Error + Send + Sync + 'static>>,
167 },
168}
169
170impl AuthenticationError {
171 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 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 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}