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    // =============
206    // Crypto errors
207    // =============
208    #[cfg(feature = "halo2_proofs")]
209    #[error("halo2 plonk error: {0}")]
210    PlonkError(String),
211
212    #[error("Wrong witness type at index: {0}")]
213    WrongWitnessType(usize),
214
215    #[error("Wrong witnesses count")]
216    WrongWitnessesCount,
217
218    #[error("Wrong public inputs count")]
219    WrongPublicInputsCount,
220
221    #[error("Unable to decrypt mint note: {0}")]
222    NoteDecryptionFailed(String),
223
224    #[error("No keypair file detected")]
225    KeypairPathNotFound,
226
227    #[error("Failed converting bytes to PublicKey")]
228    PublicKeyFromBytes,
229
230    #[error("Failed converting bytes to Coin")]
231    CoinFromBytes,
232
233    #[error("Failed converting bytes to SecretKey")]
234    SecretKeyFromBytes,
235
236    #[error("Failed converting b58 string to PublicKey")]
237    PublicKeyFromStr,
238
239    #[error("Failed converting bs58 string to SecretKey")]
240    SecretKeyFromStr,
241
242    #[error("Invalid DarkFi address")]
243    InvalidAddress,
244
245    #[error("unable to decrypt rcpt")]
246    TxRcptDecryptionError,
247
248    #[cfg(feature = "blake3")]
249    #[error(transparent)]
250    Blake3FromHexError(#[from] blake3::HexError),
251
252    // =======================
253    // Protocol-related errors
254    // =======================
255    #[error("Unsupported chain")]
256    UnsupportedChain,
257
258    #[error("JSON-RPC error: {0:?}")]
259    JsonRpcError((i32, String)),
260
261    #[cfg(feature = "rpc")]
262    #[error(transparent)]
263    RpcServerError(RpcError),
264
265    #[cfg(feature = "rpc")]
266    #[error("JSON-RPC connections exhausted")]
267    RpcConnectionsExhausted,
268
269    #[cfg(feature = "rpc")]
270    #[error("JSON-RPC server stopped")]
271    RpcServerStopped,
272
273    #[cfg(feature = "rpc")]
274    #[error("JSON-RPC client stopped")]
275    RpcClientStopped,
276
277    #[error("Unexpected JSON-RPC data received: {0}")]
278    UnexpectedJsonRpc(String),
279
280    #[error("Received proposal from unknown node")]
281    UnknownNodeError,
282
283    #[error("Public inputs are invalid")]
284    InvalidPublicInputsError,
285
286    #[error("Signature could not be verified")]
287    InvalidSignature,
288
289    #[error("State transition failed")]
290    StateTransitionError,
291
292    #[error("No forks exist")]
293    ForksNotFound,
294
295    #[error("Check if proposal extends any existing fork chains failed")]
296    ExtendedChainIndexNotFound,
297
298    #[error("Proposal contains missmatched hashes")]
299    ProposalHashesMissmatchError,
300
301    #[error("Proposal contains missmatched headers")]
302    ProposalHeadersMissmatchError,
303
304    #[error("Unable to verify transfer transaction")]
305    TransferTxVerification,
306
307    #[error("Erroneous transactions detected")]
308    ErroneousTxsDetected,
309
310    #[error("Proposal task stopped")]
311    ProposalTaskStopped,
312
313    #[error("Proposal already exists")]
314    ProposalAlreadyExists,
315
316    #[error("Consensus task stopped")]
317    ConsensusTaskStopped,
318
319    #[error("Miner task stopped")]
320    MinerTaskStopped,
321
322    #[error("Garbage collection task stopped")]
323    GarbageCollectionTaskStopped,
324
325    #[error("Calculated total work is zero")]
326    PoWTotalWorkIsZero,
327
328    #[error("Erroneous cutoff calculation")]
329    PoWCuttofCalculationError,
330
331    #[error("Provided timestamp is invalid")]
332    PoWInvalidTimestamp,
333
334    #[error("Provided output hash is greater than current target")]
335    PoWInvalidOutHash,
336
337    #[error("Contracts states monotree root missing")]
338    ContractsStatesRootNotFoundError,
339
340    #[error("Contracts states monotree root missmatch: {0} - {1}")]
341    ContractsStatesRootError(String, String),
342
343    #[error("Hashing of Monero data failed: {0}")]
344    MoneroHashingError(String),
345
346    #[error("Cannot have zero merge-mining chains")]
347    MoneroNumberOfChainZero,
348
349    #[error("MergeMineError: {0}")]
350    MoneroMergeMineError(String),
351
352    #[cfg(feature = "randomx")]
353    #[error("RandomX Error: {0}")]
354    RandomXError(String),
355
356    // ===============
357    // Database errors
358    // ===============
359    #[error("Database error: {0}")]
360    DatabaseError(String),
361
362    #[cfg(feature = "sled-overlay")]
363    #[error(transparent)]
364    SledError(#[from] sled_overlay::sled::Error),
365
366    #[cfg(feature = "sled-overlay")]
367    #[error(transparent)]
368    SledTransactionError(#[from] sled_overlay::sled::transaction::TransactionError),
369
370    #[error("Transaction {0} not found in database")]
371    TransactionNotFound(String),
372
373    #[error("Transaction already seen")]
374    TransactionAlreadySeen,
375
376    #[error("Input vectors have different length")]
377    InvalidInputLengths,
378
379    #[error("Header {0} not found in database")]
380    HeaderNotFound(String),
381
382    #[error("Block {0} is invalid")]
383    BlockIsInvalid(String),
384
385    #[error("Block version {0} is invalid")]
386    BlockVersionIsInvalid(u8),
387
388    #[error("Block {0} already in database")]
389    BlockAlreadyExists(String),
390
391    #[error("Block {0} not found in database")]
392    BlockNotFound(String),
393
394    #[error("Block with height number {0} not found in database")]
395    BlockHeightNotFound(u32),
396
397    #[error("Block difficulty for height number {0} not found in database")]
398    BlockDifficultyNotFound(u32),
399
400    #[error("Block state inverse diff for height number {0} not found in database")]
401    BlockStateInverseDiffNotFound(u32),
402
403    #[error("Block {0} contains 0 transactions")]
404    BlockContainsNoTransactions(String),
405
406    #[error("Contract {0} not found in database")]
407    ContractNotFound(String),
408
409    #[error("Contract state tree not found")]
410    ContractStateNotFound,
411
412    #[error("Contract already initialized")]
413    ContractAlreadyInitialized,
414
415    #[error("zkas bincode not found in sled database")]
416    ZkasBincodeNotFound,
417
418    // ===================
419    // wasm runtime errors
420    // ===================
421    #[cfg(feature = "wasm-runtime")]
422    #[error("Wasmer compile error: {0}")]
423    WasmerCompileError(String),
424
425    #[cfg(feature = "wasm-runtime")]
426    #[error("Wasmer export error: {0}")]
427    WasmerExportError(String),
428
429    #[cfg(feature = "wasm-runtime")]
430    #[error("Wasmer runtime error: {0}")]
431    WasmerRuntimeError(String),
432
433    #[cfg(feature = "wasm-runtime")]
434    #[error("Wasmer instantiation error: {0}")]
435    WasmerInstantiationError(String),
436
437    #[cfg(feature = "wasm-runtime")]
438    #[error("wasm memory error")]
439    WasmerMemoryError(String),
440
441    #[cfg(feature = "wasm-runtime")]
442    #[error("wasm runtime out of memory")]
443    WasmerOomError(String),
444
445    #[cfg(feature = "darkfi-sdk")]
446    #[error("Contract execution failed: {0}")]
447    ContractError(darkfi_sdk::error::ContractError),
448
449    #[cfg(feature = "darkfi-sdk")]
450    #[error("Invalid DarkTree: {0}")]
451    DarkTreeError(darkfi_sdk::error::DarkTreeError),
452
453    #[cfg(feature = "blockchain")]
454    #[error("contract wasm bincode not found")]
455    WasmBincodeNotFound,
456
457    #[cfg(feature = "wasm-runtime")]
458    #[error("contract initialize error")]
459    ContractInitError(u64),
460
461    #[cfg(feature = "wasm-runtime")]
462    #[error("contract execution error")]
463    ContractExecError(u64),
464
465    #[cfg(feature = "wasm-runtime")]
466    #[error("wasm function ACL denied")]
467    WasmFunctionAclDenied,
468
469    // ====================
470    // Event Graph errors
471    // ====================
472    #[error("Event is not found in tree: {0}")]
473    EventNotFound(String),
474
475    #[error("Event is invalid")]
476    EventIsInvalid,
477
478    // ====================
479    // Miscellaneous errors
480    // ====================
481    #[error("IO error: {0}")]
482    Io(std::io::ErrorKind),
483
484    #[error("Infallible error: {0}")]
485    InfallibleError(String),
486
487    #[cfg(feature = "smol")]
488    #[error("async_channel sender error: {0}")]
489    AsyncChannelSendError(String),
490
491    #[cfg(feature = "smol")]
492    #[error("async_channel receiver error: {0}")]
493    AsyncChannelRecvError(String),
494
495    #[cfg(feature = "util")]
496    #[error("tracing-subscriber init failed: {0}")]
497    LogInitError(String),
498
499    #[error("ValueIsNotObject")]
500    ValueIsNotObject,
501
502    #[error("No config file detected")]
503    ConfigNotFound,
504
505    #[error("Invalid config file detected")]
506    ConfigInvalid,
507
508    #[error("Configuration error: {0}")]
509    ConfigError(String),
510
511    #[error("Failed decoding bincode: {0}")]
512    ZkasDecoderError(String),
513
514    #[cfg(feature = "util")]
515    #[error("System clock is not correct!")]
516    InvalidClock,
517
518    #[error("Unsupported OS")]
519    UnsupportedOS,
520
521    #[error("System clock went backwards")]
522    BackwardsTime(std::time::SystemTimeError),
523
524    #[error("Detached task stopped")]
525    DetachedTaskStopped,
526
527    #[error("Addition overflow")]
528    AdditionOverflow,
529
530    #[error("Subtraction underflow")]
531    SubtractionUnderflow,
532
533    // ==============================================
534    // Wrappers for other error types in this library
535    // ==============================================
536    #[error(transparent)]
537    ClientFailed(#[from] ClientFailed),
538
539    #[cfg(feature = "tx")]
540    #[error(transparent)]
541    TxVerifyFailed(#[from] TxVerifyFailed),
542
543    //=============
544    // clock
545    //=============
546    #[error("clock out of sync with peers: {0}")]
547    ClockOutOfSync(String),
548
549    // ================
550    // DHT/Geode errors
551    // ================
552    #[error("Geode needs garbage collection")]
553    GeodeNeedsGc,
554
555    #[error("Geode file not found")]
556    GeodeFileNotFound,
557
558    #[error("Geode chunk not found")]
559    GeodeChunkNotFound,
560
561    #[error("Geode file route not found")]
562    GeodeFileRouteNotFound,
563
564    #[error("Geode chunk route not found")]
565    GeodeChunkRouteNotFound,
566
567    // ==================
568    // Event Graph errors
569    // ==================
570    #[error("DAG sync failed")]
571    DagSyncFailed,
572
573    #[error("Malicious flood detected")]
574    MaliciousFlood,
575
576    // =========
577    // Catch-all
578    // =========
579    #[error("{0}")]
580    Custom(String),
581}
582
583#[cfg(feature = "tx")]
584impl Error {
585    /// Auxiliary function to retrieve the vector of erroneous
586    /// transactions from a TxVerifyFailed error.
587    /// In any other case, we return the error itself.
588    pub fn retrieve_erroneous_txs(&self) -> Result<Vec<crate::tx::Transaction>> {
589        if let Self::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(erroneous_txs)) = self {
590            return Ok(erroneous_txs.clone())
591        };
592
593        Err(self.clone())
594    }
595}
596
597#[cfg(feature = "tx")]
598/// Transaction verification errors
599#[derive(Debug, Clone, thiserror::Error)]
600pub enum TxVerifyFailed {
601    #[error("Transaction {0} already exists")]
602    AlreadySeenTx(String),
603
604    #[error("Invalid transaction signature")]
605    InvalidSignature,
606
607    #[error("Missing signatures in transaction")]
608    MissingSignatures,
609
610    #[error("Missing contract calls in transaction")]
611    MissingCalls,
612
613    #[error("Invalid ZK proof in transaction")]
614    InvalidZkProof,
615
616    #[error("Missing Money::Fee call in transaction")]
617    MissingFee,
618
619    #[error("Invalid Money::Fee call in transaction")]
620    InvalidFee,
621
622    #[error("Insufficient fee paid")]
623    InsufficientFee,
624
625    #[error("Erroneous transactions found")]
626    ErroneousTxs(Vec<crate::tx::Transaction>),
627}
628
629/// Client module errors
630#[derive(Debug, Clone, thiserror::Error)]
631pub enum ClientFailed {
632    #[error("IO error: {0}")]
633    Io(std::io::ErrorKind),
634
635    #[error("Not enough value: {0}")]
636    NotEnoughValue(u64),
637
638    #[error("Invalid address: {0}")]
639    InvalidAddress(String),
640
641    #[error("Invalid amount: {0}")]
642    InvalidAmount(u64),
643
644    #[error("Invalid token ID: {0}")]
645    InvalidTokenId(String),
646
647    #[error("Internal error: {0}")]
648    InternalError(String),
649
650    #[error("Verify error: {0}")]
651    VerifyError(String),
652}
653
654#[cfg(feature = "rpc")]
655#[derive(Clone, Debug, thiserror::Error)]
656pub enum RpcError {
657    #[error("Connection closed: {0}")]
658    ConnectionClosed(String),
659
660    #[error("Invalid JSON: {0}")]
661    InvalidJson(String),
662
663    #[error("IO Error: {0}")]
664    IoError(std::io::ErrorKind),
665
666    #[error("Method not found: {0}")]
667    MethodNotFound(String),
668
669    #[error("Server-side Error: {0}")]
670    ServerError(#[from] std::sync::Arc<dyn std::error::Error + Send + Sync + 'static>),
671}
672
673#[cfg(feature = "rpc")]
674impl From<std::io::Error> for RpcError {
675    fn from(err: std::io::Error) -> Self {
676        Self::IoError(err.kind())
677    }
678}
679
680#[cfg(feature = "rpc")]
681impl From<RpcError> for Error {
682    fn from(err: RpcError) -> Self {
683        Self::RpcServerError(err)
684    }
685}
686
687impl From<Error> for ClientFailed {
688    fn from(err: Error) -> Self {
689        Self::InternalError(err.to_string())
690    }
691}
692
693impl From<std::io::Error> for ClientFailed {
694    fn from(err: std::io::Error) -> Self {
695        Self::Io(err.kind())
696    }
697}
698
699impl From<std::io::Error> for Error {
700    fn from(err: std::io::Error) -> Self {
701        Self::Io(err.kind())
702    }
703}
704
705impl From<std::time::SystemTimeError> for Error {
706    fn from(err: std::time::SystemTimeError) -> Self {
707        Self::BackwardsTime(err)
708    }
709}
710
711impl From<std::convert::Infallible> for Error {
712    fn from(err: std::convert::Infallible) -> Self {
713        Self::InfallibleError(err.to_string())
714    }
715}
716
717impl From<()> for Error {
718    fn from(_err: ()) -> Self {
719        Self::InfallibleError("Infallible".into())
720    }
721}
722
723#[cfg(feature = "net")]
724impl From<std::collections::TryReserveError> for Error {
725    fn from(err: std::collections::TryReserveError) -> Self {
726        Self::DecodePacket(err.to_string())
727    }
728}
729#[cfg(feature = "smol")]
730impl<T> From<smol::channel::SendError<T>> for Error {
731    fn from(err: smol::channel::SendError<T>) -> Self {
732        Self::AsyncChannelSendError(err.to_string())
733    }
734}
735
736#[cfg(feature = "smol")]
737impl From<smol::channel::RecvError> for Error {
738    fn from(err: smol::channel::RecvError) -> Self {
739        Self::AsyncChannelRecvError(err.to_string())
740    }
741}
742
743#[cfg(feature = "halo2_proofs")]
744impl From<halo2_proofs::plonk::Error> for Error {
745    fn from(err: halo2_proofs::plonk::Error) -> Self {
746        Self::PlonkError(err.to_string())
747    }
748}
749
750#[cfg(feature = "semver")]
751impl From<semver::Error> for Error {
752    fn from(err: semver::Error) -> Self {
753        Self::SemverError(err.to_string())
754    }
755}
756
757#[cfg(feature = "tinyjson")]
758impl From<tinyjson::JsonParseError> for Error {
759    fn from(err: tinyjson::JsonParseError) -> Self {
760        Self::JsonParseError(err.to_string())
761    }
762}
763
764#[cfg(feature = "tinyjson")]
765impl From<tinyjson::JsonGenerateError> for Error {
766    fn from(err: tinyjson::JsonGenerateError) -> Self {
767        Self::JsonGenerateError(err.to_string())
768    }
769}
770
771#[cfg(feature = "wasm-runtime")]
772impl From<wasmer::CompileError> for Error {
773    fn from(err: wasmer::CompileError) -> Self {
774        Self::WasmerCompileError(err.to_string())
775    }
776}
777
778#[cfg(feature = "wasm-runtime")]
779impl From<wasmer::ExportError> for Error {
780    fn from(err: wasmer::ExportError) -> Self {
781        Self::WasmerExportError(err.to_string())
782    }
783}
784
785#[cfg(feature = "wasm-runtime")]
786impl From<wasmer::RuntimeError> for Error {
787    fn from(err: wasmer::RuntimeError) -> Self {
788        Self::WasmerRuntimeError(err.to_string())
789    }
790}
791
792#[cfg(feature = "wasm-runtime")]
793impl From<wasmer::InstantiationError> for Error {
794    fn from(err: wasmer::InstantiationError) -> Self {
795        Self::WasmerInstantiationError(err.to_string())
796    }
797}
798
799#[cfg(feature = "wasm-runtime")]
800impl From<wasmer::MemoryAccessError> for Error {
801    fn from(err: wasmer::MemoryAccessError) -> Self {
802        Self::WasmerMemoryError(err.to_string())
803    }
804}
805
806#[cfg(feature = "wasm-runtime")]
807impl From<wasmer::MemoryError> for Error {
808    fn from(err: wasmer::MemoryError) -> Self {
809        Self::WasmerOomError(err.to_string())
810    }
811}
812
813#[cfg(feature = "darkfi-sdk")]
814impl From<darkfi_sdk::error::ContractError> for Error {
815    fn from(err: darkfi_sdk::error::ContractError) -> Self {
816        Self::ContractError(err)
817    }
818}
819
820#[cfg(feature = "darkfi-sdk")]
821impl From<darkfi_sdk::error::DarkTreeError> for Error {
822    fn from(err: darkfi_sdk::error::DarkTreeError) -> Self {
823        Self::DarkTreeError(err)
824    }
825}
826
827#[cfg(feature = "util")]
828impl From<tracing_subscriber::util::TryInitError> for Error {
829    fn from(err: tracing_subscriber::util::TryInitError) -> Self {
830        Self::LogInitError(err.to_string())
831    }
832}
833
834#[cfg(feature = "randomx")]
835impl From<randomx::RandomXError> for Error {
836    fn from(err: randomx::RandomXError) -> Self {
837        Self::RandomXError(err.to_string())
838    }
839}