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
// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
// This file is part of the HotShot repository.

// You should have received a copy of the MIT License
// along with the HotShot repository. If not, see <https://mit-license.org/>.

//! Contains the [`NetworkError`] snafu types

use std::fmt::{Debug, Display};

use futures::channel::oneshot::Canceled;
use libp2p::{
    gossipsub::PublishError,
    kad::{GetRecordError, PutRecordError},
    swarm::DialError,
    TransportError,
};
use snafu::Snafu;

/// wrapper type for errors generated by the `Network`
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum NetworkError {
    /// Error initiating dial of peer
    DialError {
        /// The underlying source of the error
        source: DialError,
    },
    /// Error during dialing or listening
    Transport {
        /// The underlying source of the error
        source: TransportError<std::io::Error>,
    },
    /// Error establishing backend connection
    TransportLaunch {
        /// The underlying source of the error
        source: std::io::Error,
    },
    /// Error building the gossipsub configuration
    #[snafu(display("Error building the gossipsub configuration: {message}"))]
    GossipsubConfig {
        /// The underlying source of the error
        message: String,
    },
    /// Error building the gossipsub instance
    #[snafu(display("Error building the gossipsub implementation {message}"))]
    GossipsubBuild {
        /// The underlying source of the error
        message: String,
    },
    /// Error if one of the channels to or from the swarm is closed
    StreamClosed,
    /// Error publishing a gossipsub message
    PublishError {
        /// The underlying source of the error
        source: PublishError,
    },
    /// Error when there are no known peers to bootstrap off
    NoKnownPeers,
}

/// Error enum for querying store
/// because for some reason, [`libp2p::kad::GetRecordError`]
/// does not derive `Error`
#[derive(Debug, Clone, Snafu)]
#[snafu(visibility(pub))]
pub enum DHTError {
    /// Get Record Error
    #[snafu(display("DHT GET internal error: {source}"))]
    GetRecord {
        /// source of error
        source: GetRecordWrapperError,
    },
    /// Get Record Error
    #[snafu(display("DHT PUT internal error: {source}"))]
    PutRecord {
        /// source of error
        source: PutRecordError,
    },
    /// nodes disagreed on the value
    #[snafu(display("Nodes disagreed on value"))]
    Disagreement,
    /// could not find 2 or more nodes that had the value
    #[snafu(display("Could not find key in DHT"))]
    NotFound,
    /// request was ignored serverside
    CancelledRequest {
        /// source of error
        source: Canceled,
    },
}

/// Wrapper Error enum for [`libp2p::kad::GetRecordError`].
/// [`libp2p::kad::GetRecordError`] does not derive [`std::error::Error`]
/// so in order to feed this into [`DHTError`] and snafu derive,
/// we need a wrapper type
#[derive(Debug, Clone)]
pub enum GetRecordWrapperError {
    /// wrapper
    GetRecordError {
        /// source of error
        source: GetRecordError,
    },
}

impl Display for GetRecordWrapperError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{self:?}")
    }
}

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