darkfi/
error.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2026 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19// Hello developer. Please add your error to the according subsection
20// that is commented, or make a new subsection. Keep it clean.
21
22/// Main result type used throughout the codebase.
23pub type Result<T> = std::result::Result<T, Error>;
24
25/// Result type used in the Client module
26pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
27
28/// General library errors used throughout the codebase.
29#[derive(Debug, Clone, thiserror::Error)]
30pub enum Error {
31    // ==============
32    // Parsing errors
33    // ==============
34    #[error("Parse failed: {0}")]
35    ParseFailed(&'static str),
36
37    #[error(transparent)]
38    ParseIntError(#[from] std::num::ParseIntError),
39
40    #[error(transparent)]
41    ParseFloatError(#[from] std::num::ParseFloatError),
42
43    #[cfg(feature = "url")]
44    #[error(transparent)]
45    UrlParseError(#[from] url::ParseError),
46
47    #[error("URL parse error: {0}")]
48    UrlParse(String),
49
50    #[error(transparent)]
51    AddrParseError(#[from] std::net::AddrParseError),
52
53    #[error("Could not parse token parameter")]
54    TokenParseError,
55
56    #[error(transparent)]
57    TryFromSliceError(#[from] std::array::TryFromSliceError),
58
59    #[cfg(feature = "semver")]
60    #[error("semver parse error: {0}")]
61    SemverError(String),
62
63    // ===============
64    // Encoding errors
65    // ===============
66    #[error("decode failed: {0}")]
67    DecodeError(&'static str),
68
69    #[error("encode failed: {0}")]
70    EncodeError(&'static str),
71
72    #[error("VarInt was encoded in a non-minimal way")]
73    NonMinimalVarInt,
74
75    #[error(transparent)]
76    Utf8Error(#[from] std::string::FromUtf8Error),
77
78    #[error(transparent)]
79    StrUtf8Error(#[from] std::str::Utf8Error),
80
81    #[cfg(feature = "tinyjson")]
82    #[error("JSON parse error: {0}")]
83    JsonParseError(String),
84
85    #[cfg(feature = "tinyjson")]
86    #[error("JSON generate error: {0}")]
87    JsonGenerateError(String),
88
89    #[cfg(feature = "toml")]
90    #[error(transparent)]
91    TomlDeserializeError(#[from] toml::de::Error),
92
93    #[cfg(feature = "bs58")]
94    #[error(transparent)]
95    Bs58DecodeError(#[from] bs58::decode::Error),
96
97    #[cfg(feature = "hex")]
98    #[error(transparent)]
99    HexDecodeError(#[from] hex::FromHexError),
100
101    #[error("Bad operation type byte")]
102    BadOperationType,
103
104    // ======================
105    // Network-related errors
106    // ======================
107    #[error("Invalid Dialer scheme")]
108    InvalidDialerScheme,
109
110    #[error("Invalid Listener scheme")]
111    InvalidListenerScheme,
112
113    #[error("Unsupported network transport: {0}")]
114    UnsupportedTransport(String),
115
116    #[error("Unsupported network transport upgrade: {0}")]
117    UnsupportedTransportUpgrade(String),
118
119    #[error("Transport request exceeds number of accepted transports")]
120    InvalidTransportRequest,
121
122    #[error("Connection failed: {0}")]
123    ConnectFailed(String),
124
125    #[cfg(feature = "system")]
126    #[error(transparent)]
127    TimeoutError(#[from] crate::system::timeout::TimeoutError),
128
129    #[error("Connection timed out")]
130    ConnectTimeout,
131
132    #[error("Channel stopped")]
133    ChannelStopped,
134
135    #[error("Channel timed out")]
136    ChannelTimeout,
137
138    #[error("Failed to reach any seeds")]
139    SeedFailed,
140
141    #[error("Network service stopped")]
142    NetworkServiceStopped,
143
144    #[error("Create listener bound to {0} failed")]
145    BindFailed(String),
146
147    #[error("Accept a new incoming connection from the listener {0} failed")]
148    AcceptConnectionFailed(String),
149
150    #[error("Accept a new tls connection from the listener {0} failed")]
151    AcceptTlsConnectionFailed(String),
152
153    #[error("Connector stopped: {0}")]
154    ConnectorStopped(String),
155
156    #[error("Network operation failed")]
157    NetworkOperationFailed,
158
159    #[error("Missing P2P message dispatcher")]
160    MissingDispatcher,
161
162    #[error("P2P message is invalid")]
163    MessageInvalid,
164
165    #[error("P2P message subsystem over metering limit")]
166    MeteringLimitExceeded,
167
168    #[cfg(feature = "arti-client")]
169    #[error(transparent)]
170    ArtiError(#[from] arti_client::Error),
171
172    #[error("Malformed packet")]
173    MalformedPacket,
174
175    #[error("Error decoding packet: {0}")]
176    DecodePacket(String),
177
178    #[error("Socks proxy error: {0}")]
179    SocksError(String),
180
181    #[error("No Socks5 URL found")]
182    NoSocks5UrlFound,
183
184    #[error("No URL found")]
185    NoUrlFound,
186
187    #[error("Tor error: {0}")]
188    TorError(String),
189
190    #[error("Node is not connected to other nodes.")]
191    NetworkNotConnected,
192
193    #[error("P2P network stopped")]
194    P2PNetworkStopped,
195
196    #[error("No such host color exists")]
197    InvalidHostColor,
198
199    #[error("No matching hostlist entry")]
200    HostDoesNotExist,
201
202    #[error("Invalid state transition: current_state={0}, end_state={1}")]
203    HostStateBlocked(String, String),
204
205    #[cfg(feature = "upnp-igd")]
206    #[error(transparent)]
207    UpnpError(#[from] oxy_upnp_igd::Error),
208
209    // =============
210    // Crypto errors
211    // =============
212    #[cfg(feature = "halo2_proofs")]
213    #[error("halo2 plonk error: {0}")]
214    PlonkError(String),
215
216    #[error("Wrong witness type at index: {0}")]
217    WrongWitnessType(usize),
218
219    #[error("Wrong witnesses count")]
220    WrongWitnessesCount,
221
222    #[error("Wrong public inputs count")]
223    WrongPublicInputsCount,
224
225    #[error("Unable to decrypt mint note: {0}")]
226    NoteDecryptionFailed(String),
227
228    #[error("No keypair file detected")]
229    KeypairPathNotFound,
230
231    #[error("Failed converting bytes to PublicKey")]
232    PublicKeyFromBytes,
233
234    #[error("Failed converting bytes to Coin")]
235    CoinFromBytes,
236
237    #[error("Failed converting bytes to SecretKey")]
238    SecretKeyFromBytes,
239
240    #[error("Failed converting b58 string to PublicKey")]
241    PublicKeyFromStr,
242
243    #[error("Failed converting bs58 string to SecretKey")]
244    SecretKeyFromStr,
245
246    #[error("Invalid DarkFi address")]
247    InvalidAddress,
248
249    #[error("unable to decrypt rcpt")]
250    TxRcptDecryptionError,
251
252    #[cfg(feature = "blake3")]
253    #[error(transparent)]
254    Blake3FromHexError(#[from] blake3::HexError),
255
256    // =======================
257    // Protocol-related errors
258    // =======================
259    #[error("Unsupported chain")]
260    UnsupportedChain,
261
262    #[error("JSON-RPC error: {0:?}")]
263    JsonRpcError((i32, String)),
264
265    #[cfg(feature = "rpc")]
266    #[error(transparent)]
267    RpcServerError(RpcError),
268
269    #[cfg(feature = "rpc")]
270    #[error("JSON-RPC connections exhausted")]
271    RpcConnectionsExhausted,
272
273    #[cfg(feature = "rpc")]
274    #[error("JSON-RPC server stopped")]
275    RpcServerStopped,
276
277    #[cfg(feature = "rpc")]
278    #[error("JSON-RPC client stopped")]
279    RpcClientStopped,
280
281    #[error("Unexpected JSON-RPC data received: {0}")]
282    UnexpectedJsonRpc(String),
283
284    #[error("Received proposal from unknown node")]
285    UnknownNodeError,
286
287    #[error("Public inputs are invalid")]
288    InvalidPublicInputsError,
289
290    #[error("Signature could not be verified")]
291    InvalidSignature,
292
293    #[error("State transition failed")]
294    StateTransitionError,
295
296    #[error("No forks exist")]
297    ForksNotFound,
298
299    #[error("Check if proposal extends any existing fork chains failed")]
300    ExtendedChainIndexNotFound,
301
302    #[error("Proposal contains missmatched hashes")]
303    ProposalHashesMissmatchError,
304
305    #[error("Proposal contains missmatched headers")]
306    ProposalHeadersMissmatchError,
307
308    #[error("Unable to verify transfer transaction")]
309    TransferTxVerification,
310
311    #[error("Erroneous transactions detected")]
312    ErroneousTxsDetected,
313
314    #[error("Proposal task stopped")]
315    ProposalTaskStopped,
316
317    #[error("Proposal already exists")]
318    ProposalAlreadyExists,
319
320    #[error("Consensus task stopped")]
321    ConsensusTaskStopped,
322
323    #[error("Miner task stopped")]
324    MinerTaskStopped,
325
326    #[error("Garbage collection task stopped")]
327    GarbageCollectionTaskStopped,
328
329    #[error("Calculated total work is zero")]
330    PoWTotalWorkIsZero,
331
332    #[error("Erroneous cutoff calculation")]
333    PoWCuttofCalculationError,
334
335    #[error("Provided timestamp is invalid")]
336    PoWInvalidTimestamp,
337
338    #[error("Provided output hash is greater than current target")]
339    PoWInvalidOutHash,
340
341    #[error("Contracts states monotree root missing")]
342    ContractsStatesRootNotFoundError,
343
344    #[error("Contracts states monotree root missmatch: {0} - {1}")]
345    ContractsStatesRootError(String, String),
346
347    #[error("Hashing of Monero data failed: {0}")]
348    MoneroHashingError(String),
349
350    #[error("Cannot have zero merge-mining chains")]
351    MoneroNumberOfChainZero,
352
353    #[error("MergeMineError: {0}")]
354    MoneroMergeMineError(String),
355
356    #[cfg(feature = "randomx")]
357    #[error("RandomX Error: {0}")]
358    RandomXError(String),
359
360    // ===============
361    // Database errors
362    // ===============
363    #[error("Database error: {0}")]
364    DatabaseError(String),
365
366    #[cfg(feature = "sled-overlay")]
367    #[error(transparent)]
368    SledError(#[from] sled_overlay::sled::Error),
369
370    #[cfg(feature = "sled-overlay")]
371    #[error(transparent)]
372    SledTransactionError(#[from] sled_overlay::sled::transaction::TransactionError),
373
374    #[error("Transaction {0} not found in database")]
375    TransactionNotFound(String),
376
377    #[error("Transaction already seen")]
378    TransactionAlreadySeen,
379
380    #[error("Input vectors have different length")]
381    InvalidInputLengths,
382
383    #[error("Header {0} not found in database")]
384    HeaderNotFound(String),
385
386    #[error("Block {0} is invalid")]
387    BlockIsInvalid(String),
388
389    #[error("Block version {0} is invalid")]
390    BlockVersionIsInvalid(u8),
391
392    #[error("Block {0} already in database")]
393    BlockAlreadyExists(String),
394
395    #[error("Block {0} not found in database")]
396    BlockNotFound(String),
397
398    #[error("Block with height number {0} not found in database")]
399    BlockHeightNotFound(u32),
400
401    #[error("Block difficulty for height number {0} not found in database")]
402    BlockDifficultyNotFound(u32),
403
404    #[error("Block state inverse diff for height number {0} not found in database")]
405    BlockStateInverseDiffNotFound(u32),
406
407    #[error("Block {0} contains 0 transactions")]
408    BlockContainsNoTransactions(String),
409
410    #[error("Contract {0} not found in database")]
411    ContractNotFound(String),
412
413    #[error("Contract state tree not found")]
414    ContractStateNotFound,
415
416    #[error("Contract already initialized")]
417    ContractAlreadyInitialized,
418
419    #[error("zkas bincode not found in sled database")]
420    ZkasBincodeNotFound,
421
422    // ===================
423    // wasm runtime errors
424    // ===================
425    #[cfg(feature = "wasm-runtime")]
426    #[error("Wasmer compile error: {0}")]
427    WasmerCompileError(String),
428
429    #[cfg(feature = "wasm-runtime")]
430    #[error("Wasmer export error: {0}")]
431    WasmerExportError(String),
432
433    #[cfg(feature = "wasm-runtime")]
434    #[error("Wasmer runtime error: {0}")]
435    WasmerRuntimeError(String),
436
437    #[cfg(feature = "wasm-runtime")]
438    #[error("Wasmer instantiation error: {0}")]
439    WasmerInstantiationError(String),
440
441    #[cfg(feature = "wasm-runtime")]
442    #[error("wasm memory error")]
443    WasmerMemoryError(String),
444
445    #[cfg(feature = "wasm-runtime")]
446    #[error("wasm runtime out of memory")]
447    WasmerOomError(String),
448
449    #[cfg(feature = "darkfi-sdk")]
450    #[error("Contract execution failed: {0}")]
451    ContractError(darkfi_sdk::error::ContractError),
452
453    #[cfg(feature = "darkfi-sdk")]
454    #[error("Invalid DarkTree: {0}")]
455    DarkTreeError(darkfi_sdk::error::DarkTreeError),
456
457    #[cfg(feature = "blockchain")]
458    #[error("contract wasm bincode not found")]
459    WasmBincodeNotFound,
460
461    #[cfg(feature = "wasm-runtime")]
462    #[error("contract initialize error")]
463    ContractInitError(u64),
464
465    #[cfg(feature = "wasm-runtime")]
466    #[error("contract execution error")]
467    ContractExecError(u64),
468
469    #[cfg(feature = "wasm-runtime")]
470    #[error("wasm function ACL denied")]
471    WasmFunctionAclDenied,
472
473    // ====================
474    // Event Graph errors
475    // ====================
476    #[error("Event is not found in tree: {0}")]
477    EventNotFound(String),
478
479    #[error("Event is invalid")]
480    EventIsInvalid,
481
482    #[error("Header is invalid")]
483    HeaderIsInvalid,
484
485    // ====================
486    // Miscellaneous errors
487    // ====================
488    #[error("IO error: {0}")]
489    Io(std::io::ErrorKind),
490
491    #[error("Infallible error: {0}")]
492    InfallibleError(String),
493
494    #[cfg(feature = "smol")]
495    #[error("async_channel sender error: {0}")]
496    AsyncChannelSendError(String),
497
498    #[cfg(feature = "smol")]
499    #[error("async_channel receiver error: {0}")]
500    AsyncChannelRecvError(String),
501
502    #[cfg(feature = "util")]
503    #[error("tracing-subscriber init failed: {0}")]
504    LogInitError(String),
505
506    #[error("ValueIsNotObject")]
507    ValueIsNotObject,
508
509    #[error("No config file detected")]
510    ConfigNotFound,
511
512    #[error("Invalid config file detected")]
513    ConfigInvalid,
514
515    #[error("Configuration error: {0}")]
516    ConfigError(String),
517
518    #[error("Failed decoding bincode: {0}")]
519    ZkasDecoderError(String),
520
521    #[cfg(feature = "util")]
522    #[error("System clock is not correct!")]
523    InvalidClock,
524
525    #[error("Unsupported OS")]
526    UnsupportedOS,
527
528    #[error("System clock went backwards")]
529    BackwardsTime(std::time::SystemTimeError),
530
531    #[error("Detached task stopped")]
532    DetachedTaskStopped,
533
534    #[error("Addition overflow")]
535    AdditionOverflow,
536
537    #[error("Subtraction underflow")]
538    SubtractionUnderflow,
539
540    // ==============================================
541    // Wrappers for other error types in this library
542    // ==============================================
543    #[error(transparent)]
544    ClientFailed(#[from] ClientFailed),
545
546    #[cfg(feature = "tx")]
547    #[error(transparent)]
548    TxVerifyFailed(#[from] TxVerifyFailed),
549
550    //=============
551    // clock
552    //=============
553    #[error("clock out of sync with peers: {0}")]
554    ClockOutOfSync(String),
555
556    // ================
557    // DHT/Geode errors
558    // ================
559    #[error("Geode needs garbage collection")]
560    GeodeNeedsGc,
561
562    #[error("Geode file not found")]
563    GeodeFileNotFound,
564
565    #[error("Geode chunk not found")]
566    GeodeChunkNotFound,
567
568    #[error("Geode file route not found")]
569    GeodeFileRouteNotFound,
570
571    #[error("Geode chunk route not found")]
572    GeodeChunkRouteNotFound,
573
574    // ==================
575    // Event Graph errors
576    // ==================
577    #[error("Static DAG sync failed")]
578    StaticDagSyncFailed,
579
580    #[error("DAG sync failed")]
581    DagSyncFailed,
582
583    #[error("Malicious flood detected")]
584    MaliciousFlood,
585
586    // =========
587    // Catch-all
588    // =========
589    #[error("{0}")]
590    Custom(String),
591}
592
593#[cfg(feature = "tx")]
594impl Error {
595    /// Auxiliary function to retrieve the vector of erroneous
596    /// transactions from a TxVerifyFailed error.
597    /// In any other case, we return the error itself.
598    pub fn retrieve_erroneous_txs(&self) -> Result<Vec<crate::tx::Transaction>> {
599        if let Self::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(erroneous_txs)) = self {
600            return Ok(erroneous_txs.clone())
601        };
602
603        Err(self.clone())
604    }
605}
606
607#[cfg(feature = "tx")]
608/// Transaction verification errors
609#[derive(Debug, Clone, thiserror::Error)]
610pub enum TxVerifyFailed {
611    #[error("Transaction {0} already exists")]
612    AlreadySeenTx(String),
613
614    #[error("Invalid transaction signature")]
615    InvalidSignature,
616
617    #[error("Missing signatures in transaction")]
618    MissingSignatures,
619
620    #[error("Missing contract calls in transaction")]
621    MissingCalls,
622
623    #[error("Invalid ZK proof in transaction")]
624    InvalidZkProof,
625
626    #[error("Missing Money::Fee call in transaction")]
627    MissingFee,
628
629    #[error("Invalid Money::Fee call in transaction")]
630    InvalidFee,
631
632    #[error("Insufficient fee paid")]
633    InsufficientFee,
634
635    #[error("Erroneous transactions found")]
636    ErroneousTxs(Vec<crate::tx::Transaction>),
637}
638
639/// Client module errors
640#[derive(Debug, Clone, thiserror::Error)]
641pub enum ClientFailed {
642    #[error("IO error: {0}")]
643    Io(std::io::ErrorKind),
644
645    #[error("Not enough value: {0}")]
646    NotEnoughValue(u64),
647
648    #[error("Invalid address: {0}")]
649    InvalidAddress(String),
650
651    #[error("Invalid amount: {0}")]
652    InvalidAmount(u64),
653
654    #[error("Invalid token ID: {0}")]
655    InvalidTokenId(String),
656
657    #[error("Internal error: {0}")]
658    InternalError(String),
659
660    #[error("Verify error: {0}")]
661    VerifyError(String),
662}
663
664#[cfg(feature = "rpc")]
665#[derive(Clone, Debug, thiserror::Error)]
666pub enum RpcError {
667    #[error("Connection closed: {0}")]
668    ConnectionClosed(String),
669
670    #[error("Invalid JSON: {0}")]
671    InvalidJson(String),
672
673    #[error("IO Error: {0}")]
674    IoError(std::io::ErrorKind),
675
676    #[error("Method not found: {0}")]
677    MethodNotFound(String),
678
679    #[error("Server-side Error: {0}")]
680    ServerError(#[from] std::sync::Arc<dyn std::error::Error + Send + Sync + 'static>),
681}
682
683#[cfg(feature = "rpc")]
684impl From<std::io::Error> for RpcError {
685    fn from(err: std::io::Error) -> Self {
686        Self::IoError(err.kind())
687    }
688}
689
690#[cfg(feature = "rpc")]
691impl From<RpcError> for Error {
692    fn from(err: RpcError) -> Self {
693        Self::RpcServerError(err)
694    }
695}
696
697impl From<Error> for ClientFailed {
698    fn from(err: Error) -> Self {
699        Self::InternalError(err.to_string())
700    }
701}
702
703impl From<std::io::Error> for ClientFailed {
704    fn from(err: std::io::Error) -> Self {
705        Self::Io(err.kind())
706    }
707}
708
709impl From<std::io::Error> for Error {
710    fn from(err: std::io::Error) -> Self {
711        Self::Io(err.kind())
712    }
713}
714
715impl From<std::time::SystemTimeError> for Error {
716    fn from(err: std::time::SystemTimeError) -> Self {
717        Self::BackwardsTime(err)
718    }
719}
720
721impl From<std::convert::Infallible> for Error {
722    fn from(err: std::convert::Infallible) -> Self {
723        Self::InfallibleError(err.to_string())
724    }
725}
726
727impl From<()> for Error {
728    fn from(_err: ()) -> Self {
729        Self::InfallibleError("Infallible".into())
730    }
731}
732
733#[cfg(feature = "net")]
734impl From<std::collections::TryReserveError> for Error {
735    fn from(err: std::collections::TryReserveError) -> Self {
736        Self::DecodePacket(err.to_string())
737    }
738}
739#[cfg(feature = "smol")]
740impl<T> From<smol::channel::SendError<T>> for Error {
741    fn from(err: smol::channel::SendError<T>) -> Self {
742        Self::AsyncChannelSendError(err.to_string())
743    }
744}
745
746#[cfg(feature = "smol")]
747impl From<smol::channel::RecvError> for Error {
748    fn from(err: smol::channel::RecvError) -> Self {
749        Self::AsyncChannelRecvError(err.to_string())
750    }
751}
752
753#[cfg(feature = "halo2_proofs")]
754impl From<halo2_proofs::plonk::Error> for Error {
755    fn from(err: halo2_proofs::plonk::Error) -> Self {
756        Self::PlonkError(err.to_string())
757    }
758}
759
760#[cfg(feature = "semver")]
761impl From<semver::Error> for Error {
762    fn from(err: semver::Error) -> Self {
763        Self::SemverError(err.to_string())
764    }
765}
766
767#[cfg(feature = "tinyjson")]
768impl From<tinyjson::JsonParseError> for Error {
769    fn from(err: tinyjson::JsonParseError) -> Self {
770        Self::JsonParseError(err.to_string())
771    }
772}
773
774#[cfg(feature = "tinyjson")]
775impl From<tinyjson::JsonGenerateError> for Error {
776    fn from(err: tinyjson::JsonGenerateError) -> Self {
777        Self::JsonGenerateError(err.to_string())
778    }
779}
780
781#[cfg(feature = "wasm-runtime")]
782impl From<wasmer::CompileError> for Error {
783    fn from(err: wasmer::CompileError) -> Self {
784        Self::WasmerCompileError(err.to_string())
785    }
786}
787
788#[cfg(feature = "wasm-runtime")]
789impl From<wasmer::ExportError> for Error {
790    fn from(err: wasmer::ExportError) -> Self {
791        Self::WasmerExportError(err.to_string())
792    }
793}
794
795#[cfg(feature = "wasm-runtime")]
796impl From<wasmer::RuntimeError> for Error {
797    fn from(err: wasmer::RuntimeError) -> Self {
798        Self::WasmerRuntimeError(err.to_string())
799    }
800}
801
802#[cfg(feature = "wasm-runtime")]
803impl From<wasmer::InstantiationError> for Error {
804    fn from(err: wasmer::InstantiationError) -> Self {
805        Self::WasmerInstantiationError(err.to_string())
806    }
807}
808
809#[cfg(feature = "wasm-runtime")]
810impl From<wasmer::MemoryAccessError> for Error {
811    fn from(err: wasmer::MemoryAccessError) -> Self {
812        Self::WasmerMemoryError(err.to_string())
813    }
814}
815
816#[cfg(feature = "wasm-runtime")]
817impl From<wasmer::MemoryError> for Error {
818    fn from(err: wasmer::MemoryError) -> Self {
819        Self::WasmerOomError(err.to_string())
820    }
821}
822
823#[cfg(feature = "darkfi-sdk")]
824impl From<darkfi_sdk::error::ContractError> for Error {
825    fn from(err: darkfi_sdk::error::ContractError) -> Self {
826        Self::ContractError(err)
827    }
828}
829
830#[cfg(feature = "darkfi-sdk")]
831impl From<darkfi_sdk::error::DarkTreeError> for Error {
832    fn from(err: darkfi_sdk::error::DarkTreeError) -> Self {
833        Self::DarkTreeError(err)
834    }
835}
836
837#[cfg(feature = "util")]
838impl From<tracing_subscriber::util::TryInitError> for Error {
839    fn from(err: tracing_subscriber::util::TryInitError) -> Self {
840        Self::LogInitError(err.to_string())
841    }
842}
843
844#[cfg(feature = "randomx")]
845impl From<randomx::RandomXError> for Error {
846    fn from(err: randomx::RandomXError) -> Self {
847        Self::RandomXError(err.to_string())
848    }
849}