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