Skip to main content

dusk_vm/
error.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use dusk_core::TxPreconditionError;
8use dusk_core::transfer::PANIC_NONCE_NOT_READY;
9use piecrust::Error;
10
11/// Errors that can occur during transaction execution in the VM.
12///
13/// This enum encapsulates different types of errors that may arise, including
14/// precondition failures, unspendable errors, and failed refunds.
15/// Each variant provides context about the nature of the error, allowing for
16/// more precise error handling and debugging.
17#[derive(Debug, thiserror::Error)]
18pub enum ExecutionError {
19    /// Occurs when a refund operation fails after transaction execution.
20    #[error("Failed refund: {0}")]
21    FailedRefund(Error),
22
23    /// Occurs when the transaction is valid but cannot be processed at the
24    /// moment, like when the nonce used is not the next one
25    #[error("Nonce not ready to be used yet")]
26    NotReady,
27
28    /// Occurs when a precondition for transaction execution is not met.
29    #[error("Precondition error: {0}")]
30    Precondition(String),
31
32    /// Occurs when a transaction is deemed unspendable due to an error during
33    /// execution.
34    #[error("Unspendable: {0}")]
35    Unspendable(Error),
36}
37
38impl ExecutionError {
39    /// Creates a new `ExecutionError` with the `Precondition` variant.
40    pub fn precondition<T: ToString>(msg: T) -> Self {
41        Self::Precondition(msg.to_string())
42    }
43
44    /// Creates a new `ExecutionError` from an existing `Error` happening during
45    /// the spend_or_execute phase, categorizing it as `Unspendable` unless it's
46    /// a specific nonce not ready panic.
47    pub fn from_spend_and_execute(inner: Error) -> Self {
48        if let Error::Panic(val) = &inner
49            && val == PANIC_NONCE_NOT_READY
50        {
51            Self::NotReady
52        } else {
53            Self::Unspendable(inner)
54        }
55    }
56    /// Creates a new `ExecutionError` with the `FailedRefund` variant.
57    pub fn failed_refund(inner: Error) -> Self {
58        Self::FailedRefund(inner)
59    }
60}
61
62impl From<TxPreconditionError> for ExecutionError {
63    fn from(err: TxPreconditionError) -> Self {
64        ExecutionError::Precondition(err.legacy_to_string())
65    }
66}