miden_lib/errors/
transaction_errors.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::error::Error;
4
5use miden_objects::note::NoteMetadata;
6use miden_objects::transaction::TransactionSummary;
7use miden_objects::{AccountDeltaError, AssetError, Felt, NoteError, Word};
8use thiserror::Error;
9
10// TRANSACTION KERNEL ERROR
11// ================================================================================================
12
13#[derive(Debug, Error)]
14pub enum TransactionKernelError {
15    #[error("failed to add asset to account delta")]
16    AccountDeltaAddAssetFailed(#[source] AccountDeltaError),
17    #[error("failed to remove asset to account delta")]
18    AccountDeltaRemoveAssetFailed(#[source] AccountDeltaError),
19    #[error("failed to add asset to note")]
20    FailedToAddAssetToNote(#[source] NoteError),
21    #[error("note input data has hash {actual} but expected hash {expected}")]
22    InvalidNoteInputs { expected: Word, actual: Word },
23    #[error(
24        "storage slot index {actual} is invalid, must be smaller than the number of account storage slots {max}"
25    )]
26    InvalidStorageSlotIndex { max: u64, actual: u64 },
27    #[error(
28        "failed to respond to signature requested since no authenticator is assigned to the host"
29    )]
30    MissingAuthenticator,
31    #[error("failed to generate signature")]
32    SignatureGenerationFailed(#[source] Box<dyn Error + Send + Sync + 'static>),
33    #[error("transaction returned unauthorized event but a commitment did not match: {0}")]
34    TransactionSummaryCommitmentMismatch(#[source] Box<dyn Error + Send + Sync + 'static>),
35    #[error("failed to construct transaction summary")]
36    TransactionSummaryConstructionFailed(#[source] Box<dyn Error + Send + Sync + 'static>),
37    #[error("asset data extracted from the stack by event handler `{handler}` is not well formed")]
38    MalformedAssetInEventHandler {
39        handler: &'static str,
40        source: AssetError,
41    },
42    #[error(
43        "note inputs data extracted from the advice map by the event handler is not well formed"
44    )]
45    MalformedNoteInputs(#[source] NoteError),
46    #[error("note metadata created by the event handler is not well formed")]
47    MalformedNoteMetadata(#[source] NoteError),
48    #[error(
49        "note script data `{data:?}` extracted from the advice map by the event handler is not well formed"
50    )]
51    MalformedNoteScript {
52        data: Vec<Felt>,
53        // This is always a DeserializationError, but we can't import it directly here without
54        // adding dependencies, so we make it a trait object instead.
55        source: Box<dyn Error + Send + Sync + 'static>,
56    },
57    #[error("recipient data `{0:?}` in the advice provider is not well formed")]
58    MalformedRecipientData(Vec<Felt>),
59    #[error("cannot add asset to note with index {0}, note does not exist in the advice provider")]
60    MissingNote(u64),
61    #[error(
62        "public note with metadata {0:?} and recipient digest {1} is missing details in the advice provider"
63    )]
64    PublicNoteMissingDetails(NoteMetadata, Word),
65    #[error(
66        "note input data in advice provider contains fewer elements ({actual}) than specified ({specified}) by its inputs length"
67    )]
68    TooFewElementsForNoteInputs { specified: u64, actual: u64 },
69    #[error("account procedure with procedure root {0} is not in the advice provider")]
70    UnknownAccountProcedure(Word),
71    #[error("code commitment {0} is not in the advice provider")]
72    UnknownCodeCommitment(Word),
73    #[error("account storage slots number is missing in memory at address {0}")]
74    AccountStorageSlotsNumMissing(u32),
75    #[error("account nonce can only be incremented once")]
76    NonceCanOnlyIncrementOnce,
77    #[error("failed to convert fee asset into fungible asset")]
78    FailedToConvertFeeAsset(#[source] AssetError),
79    #[error(
80        "native asset amount {account_balance} in the account vault is not sufficient to cover the transaction fee of {tx_fee}"
81    )]
82    InsufficientFee { account_balance: u64, tx_fee: u64 },
83    /// This variant signals that a signature over the contained commitments is required, but
84    /// missing.
85    #[error("transaction requires a signature")]
86    Unauthorized(Box<TransactionSummary>),
87}
88
89// TRANSACTION EVENT PARSING ERROR
90// ================================================================================================
91
92#[derive(Debug, Error)]
93pub enum TransactionEventError {
94    #[error("event id {0} is not a valid transaction event")]
95    InvalidTransactionEvent(u32),
96    #[error("event id {0} is not a transaction kernel event")]
97    NotTransactionEvent(u32),
98    #[error("event id {0} can only be emitted from the root context")]
99    NotRootContext(u32),
100}
101
102// TRANSACTION TRACE PARSING ERROR
103// ================================================================================================
104
105#[derive(Debug, Error)]
106pub enum TransactionTraceParsingError {
107    #[error("trace id {0} is an unknown transaction kernel trace")]
108    UnknownTransactionTrace(u32),
109}
110
111#[cfg(test)]
112mod error_assertions {
113    use super::*;
114
115    /// Asserts at compile time that the passed error has Send + Sync + 'static bounds.
116    fn _assert_error_is_send_sync_static<E: core::error::Error + Send + Sync + 'static>(_: E) {}
117
118    fn _assert_transaction_kernel_error_bounds(err: TransactionKernelError) {
119        _assert_error_is_send_sync_static(err);
120    }
121}