1use alloc::{boxed::Box, string::String};
2use core::error::Error;
3
4use miden_objects::{
5 AccountError, Felt, ProvenTransactionError, TransactionInputError, TransactionOutputError,
6 account::AccountId, assembly::diagnostics::reporting::PrintDiagnostic, block::BlockNumber,
7 crypto::merkle::SmtProofError, note::NoteId,
8};
9use miden_verifier::VerificationError;
10use thiserror::Error;
11use vm_processor::ExecutionError;
12
13#[derive(Debug, Error)]
17pub enum TransactionExecutorError {
18 #[error("failed to fetch transaction inputs from the data store")]
19 FetchTransactionInputsFailed(#[source] DataStoreError),
20 #[error("foreign account inputs for ID {0} are not anchored on reference block")]
21 ForeignAccountNotAnchoredInReference(AccountId),
22 #[error("failed to create transaction inputs")]
23 InvalidTransactionInputs(#[source] TransactionInputError),
24 #[error("input account ID {input_id} does not match output account ID {output_id}")]
25 InconsistentAccountId {
26 input_id: AccountId,
27 output_id: AccountId,
28 },
29 #[error("expected account nonce {expected:?}, found {actual:?}")]
30 InconsistentAccountNonceDelta {
31 expected: Option<Felt>,
32 actual: Option<Felt>,
33 },
34 #[error("account witness provided for account ID {0} is invalid")]
35 InvalidAccountWitness(AccountId, #[source] SmtProofError),
36 #[error(
37 "input note {0} was created in a block past the transaction reference block number ({1})"
38 )]
39 NoteBlockPastReferenceBlock(NoteId, BlockNumber),
40 #[error("failed to create transaction host")]
41 TransactionHostCreationFailed(#[source] TransactionHostError),
42 #[error("failed to construct transaction outputs")]
43 TransactionOutputConstructionFailed(#[source] TransactionOutputError),
44 #[error("failed to execute transaction kernel program:\n{}", PrintDiagnostic::new(.0))]
47 TransactionProgramExecutionFailed(ExecutionError),
48}
49
50#[derive(Debug, Error)]
54pub enum TransactionProverError {
55 #[error("failed to apply account delta")]
56 AccountDeltaApplyFailed(#[source] AccountError),
57 #[error("transaction inputs are not valid")]
58 InvalidTransactionInputs(#[source] TransactionInputError),
59 #[error("failed to construct transaction outputs")]
60 TransactionOutputConstructionFailed(#[source] TransactionOutputError),
61 #[error("failed to build proven transaction")]
62 ProvenTransactionBuildFailed(#[source] ProvenTransactionError),
63 #[error("failed to execute transaction kernel program:\n{}", PrintDiagnostic::new(.0))]
66 TransactionProgramExecutionFailed(ExecutionError),
67 #[error("failed to create transaction host")]
68 TransactionHostCreationFailed(#[source] TransactionHostError),
69 #[error("{error_msg}")]
71 Other {
72 error_msg: Box<str>,
73 source: Option<Box<dyn Error + Send + Sync + 'static>>,
75 },
76}
77
78impl TransactionProverError {
79 pub fn other(message: impl Into<String>) -> Self {
82 let message: String = message.into();
83 Self::Other { error_msg: message.into(), source: None }
84 }
85
86 pub fn other_with_source(
89 message: impl Into<String>,
90 source: impl Error + Send + Sync + 'static,
91 ) -> Self {
92 let message: String = message.into();
93 Self::Other {
94 error_msg: message.into(),
95 source: Some(Box::new(source)),
96 }
97 }
98}
99
100#[derive(Debug, Error)]
104pub enum TransactionVerifierError {
105 #[error("failed to verify transaction")]
106 TransactionVerificationFailed(#[source] VerificationError),
107 #[error("transaction proof security level is {actual} but must be at least {expected_minimum}")]
108 InsufficientProofSecurityLevel { actual: u32, expected_minimum: u32 },
109}
110
111#[derive(Debug, Error)]
115pub enum TransactionHostError {
116 #[error("{0}")]
117 AccountProcedureIndexMapError(String),
118 #[error("failed to create account procedure info")]
119 AccountProcedureInfoCreationFailed(#[source] AccountError),
120}
121
122#[derive(Debug, Error)]
126pub enum DataStoreError {
127 #[error("account with id {0} not found in data store")]
128 AccountNotFound(AccountId),
129 #[error("block with number {0} not found in data store")]
130 BlockNotFound(BlockNumber),
131 #[error("{error_msg}")]
134 Other {
135 error_msg: Box<str>,
136 source: Option<Box<dyn Error + Send + Sync + 'static>>,
138 },
139}
140
141impl DataStoreError {
142 pub fn other(message: impl Into<String>) -> Self {
144 let message: String = message.into();
145 Self::Other { error_msg: message.into(), source: None }
146 }
147
148 pub fn other_with_source(
151 message: impl Into<String>,
152 source: impl Error + Send + Sync + 'static,
153 ) -> Self {
154 let message: String = message.into();
155 Self::Other {
156 error_msg: message.into(),
157 source: Some(Box::new(source)),
158 }
159 }
160}
161
162#[derive(Debug, Error)]
166pub enum AuthenticationError {
167 #[error("signature rejected: {0}")]
168 RejectedSignature(String),
169 #[error("unknown public key: {0}")]
170 UnknownPublicKey(String),
171 #[error("{error_msg}")]
174 Other {
175 error_msg: Box<str>,
176 source: Option<Box<dyn Error + Send + Sync + 'static>>,
178 },
179}
180
181impl AuthenticationError {
182 pub fn other(message: impl Into<String>) -> Self {
185 let message: String = message.into();
186 Self::Other { error_msg: message.into(), source: None }
187 }
188
189 pub fn other_with_source(
192 message: impl Into<String>,
193 source: impl Error + Send + Sync + 'static,
194 ) -> Self {
195 let message: String = message.into();
196 Self::Other {
197 error_msg: message.into(),
198 source: Some(Box::new(source)),
199 }
200 }
201}
202
203#[cfg(test)]
204mod error_assertions {
205 use super::*;
206
207 fn _assert_error_is_send_sync_static<E: core::error::Error + Send + Sync + 'static>(_: E) {}
209
210 fn _assert_data_store_error_bounds(err: DataStoreError) {
211 _assert_error_is_send_sync_static(err);
212 }
213
214 fn _assert_authentication_error_bounds(err: AuthenticationError) {
215 _assert_error_is_send_sync_static(err);
216 }
217}