rusk/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use std::{fmt, io};

use dusk_bytes::Serializable;
use dusk_core::{
    signatures::bls::PublicKey as BlsPublicKey, transfer::phoenix::CoreError,
    BlsScalar, Error as ExecErr,
};
use dusk_vm::Error as VMError;

#[derive(Debug)]
pub enum Error {
    /// Failed to register a backend for persistence
    BackendRegistrationFailed,
    /// Failed to restore a network state from disk
    RestoreFailed,
    /// Proof verification failure
    ProofVerification,
    /// Out of gas in block execution
    OutOfGas,
    /// Repeated nullifier in transaction verification
    RepeatingNullifiers(Vec<BlsScalar>),
    /// Repeated nullifier in the same transaction
    DoubleNullifiers,
    /// Repeating a nonce that has already been used
    RepeatingNonce(Box<BlsPublicKey>, u64),
    /// Wrong inputs and/or outputs in the transaction verification
    InvalidCircuitArguments(usize, usize),
    /// Failed to build a Rusk instance
    BuilderInvalidState,
    /// Failed to fetch opening
    OpeningPositionNotFound(u64),
    /// Failed to fetch opening due to undefined Note
    OpeningNoteUndefined(u64),
    /// Bytes Serialization Errors
    Serialization(dusk_bytes::Error),
    /// Originating from transaction-creation
    Transaction(ExecErr),
    /// Originating from Phoenix.
    Phoenix(CoreError),
    /// Piecrust VM internal Errors
    Vm(VMError),
    /// IO Errors
    Io(io::Error),
    /// Failed to produce proper state
    #[cfg(feature = "chain")]
    InconsistentState(Box<dusk_consensus::operations::VerificationOutput>),
    /// Other
    Other(Box<dyn std::error::Error>),
    /// Commit not found amongst existing commits
    CommitNotFound([u8; 32]),
    /// Invalid credits count
    InvalidCreditsCount(u64, usize),
    /// Memo too large
    MemoTooLarge(usize),
    /// Chain tip different from the expected one
    TipChanged,
}

impl std::error::Error for Error {}

impl From<Box<dyn std::error::Error>> for Error {
    fn from(err: Box<dyn std::error::Error>) -> Self {
        Error::Other(err)
    }
}

impl From<VMError> for Error {
    fn from(err: VMError) -> Self {
        Error::Vm(err)
    }
}

impl From<dusk_core::Error> for Error {
    fn from(err: ExecErr) -> Self {
        match err {
            ExecErr::InsufficientBalance => {
                Self::Transaction(ExecErr::InsufficientBalance)
            }
            ExecErr::Replay => Self::Transaction(ExecErr::Replay),
            ExecErr::PhoenixOwnership => {
                Self::Transaction(ExecErr::PhoenixOwnership)
            }
            ExecErr::PhoenixCircuit(e) => {
                Self::Transaction(ExecErr::PhoenixCircuit(e))
            }
            ExecErr::PhoenixProver(e) => {
                Self::Transaction(ExecErr::PhoenixProver(e))
            }
            ExecErr::InvalidData => {
                Self::Serialization(dusk_bytes::Error::InvalidData)
            }
            ExecErr::BadLength(found, expected) => {
                Self::Serialization(dusk_bytes::Error::BadLength {
                    found,
                    expected,
                })
            }
            ExecErr::InvalidChar(ch, index) => {
                Self::Serialization(dusk_bytes::Error::InvalidChar {
                    ch,
                    index,
                })
            }
            ExecErr::Rkyv(e) => Self::Transaction(ExecErr::Rkyv(e)),
            ExecErr::MemoTooLarge(size) => Self::MemoTooLarge(size),
        }
    }
}

impl From<dusk_bytes::Error> for Error {
    fn from(err: dusk_bytes::Error) -> Self {
        Self::Serialization(err)
    }
}

impl From<CoreError> for Error {
    fn from(pe: CoreError) -> Self {
        Self::Phoenix(pe)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::BackendRegistrationFailed => {
                write!(f, "Failed to register a backend for persistence")
            }
            Error::RestoreFailed => {
                write!(f, "Failed to restore a network state")
            }
            Error::BuilderInvalidState => {
                write!(f, "Failed to build a Rusk instance")
            }
            Error::OpeningPositionNotFound(pos) => {
                write!(f, "Failed to fetch opening of position {pos}")
            }
            Error::OpeningNoteUndefined(pos) => {
                write!(f, "Note {pos} not found, opening of position")
            }
            Error::Serialization(err) => {
                write!(f, "Serialization Error: {err:?}")
            }
            Error::Vm(err) => write!(f, "VM Error: {err}"),
            Error::Io(err) => write!(f, "IO Error: {err}"),
            Error::Transaction(err) => write!(f, "Transaction Error: {err}"),
            Error::Phoenix(err) => write!(f, "Phoenix error: {err}"),
            Error::Other(err) => write!(f, "Other error: {err}"),
            Error::ProofVerification => write!(f, "Proof verification failure"),
            Error::OutOfGas => write!(f, "Out of gas"),
            Error::RepeatingNullifiers(n) => {
                write!(f, "Nullifiers already spent: {n:?}")
            }
            Error::DoubleNullifiers => write!(f, "Double nullifiers"),
            Error::RepeatingNonce(account, nonce) => {
                let encoded_account =
                    bs58::encode(&account.to_bytes()).into_string();
                write!(f, "Nonce repeat: {encoded_account} {nonce}")
            }
            Error::InvalidCircuitArguments(inputs_len, outputs_len) => {
                write!(f,"Expected: 0 < (inputs: {inputs_len}) < 5, 0 ≤ (outputs: {outputs_len}) < 3")
            }
            #[cfg(feature = "chain")]
            Error::InconsistentState(vo) => {
                write!(f, "Inconsistent state verification data {vo}",)
            }
            Error::CommitNotFound(commit_id) => {
                write!(f, "Commit not found, id = {}", hex::encode(commit_id),)
            }
            Error::InvalidCreditsCount(height, credits) => {
                write!(f, "Invalid credits: H= {height}, credits= {credits}",)
            }
            Error::MemoTooLarge(size) => {
                write!(f, "The memo size {size} is too large")
            }
            Error::TipChanged => {
                write!(f, "Chain tip different from the expected one")
            }
        }
    }
}