Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/libp2p/peer_id.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (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 General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
use alloc::{string::String, vec, vec::Vec};
19
use core::{cmp, fmt, hash, str::FromStr};
20
21
use super::multihash;
22
use crate::util::protobuf;
23
24
/// Public key of a node's identity.
25
///
26
/// Libp2p specifies multiple different possible algorithms, but only Ed25519 support is
27
/// mandatory.
28
#[derive(Clone, Debug, PartialEq, Eq)]
29
pub enum PublicKey {
30
    /// An Ed25519 public key.
31
    Ed25519([u8; 32]),
32
}
33
34
impl PublicKey {
35
    /// Encode the public key into a Protobuf structure for exchange with other nodes.
36
    ///
37
    /// As indicated in the libp2p specification, the encoding is done deterministically despite
38
    /// the fact that the Protobuf format isn't deterministic.
39
    ///
40
    /// See <https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#keys>.
41
220
    pub fn to_protobuf_encoding(&self) -> Vec<u8> {
42
220
        match self {
43
220
            PublicKey::Ed25519(key) => {
44
220
                const CAPACITY: usize = 32 + 4;
45
220
                let mut out = Vec::with_capacity(CAPACITY);
46
660
                for 
slice440
in protobuf::enum_tag_encode(1, 1) {
47
440
                    out.extend_from_slice(slice.as_ref());
48
440
                }
49
660
                for slice in protobuf::bytes_tag_encode(2, 
key220
) {
50
660
                    out.extend_from_slice(slice.as_ref());
51
660
                }
52
220
                debug_assert_eq!(out.len(), CAPACITY);
53
220
                out
54
220
            }
55
220
        }
56
220
    }
_RNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB2_9PublicKey20to_protobuf_encoding
Line
Count
Source
41
53
    pub fn to_protobuf_encoding(&self) -> Vec<u8> {
42
53
        match self {
43
53
            PublicKey::Ed25519(key) => {
44
53
                const CAPACITY: usize = 32 + 4;
45
53
                let mut out = Vec::with_capacity(CAPACITY);
46
159
                for 
slice106
in protobuf::enum_tag_encode(1, 1) {
47
106
                    out.extend_from_slice(slice.as_ref());
48
106
                }
49
159
                for slice in protobuf::bytes_tag_encode(2, 
key53
) {
50
159
                    out.extend_from_slice(slice.as_ref());
51
159
                }
52
53
                debug_assert_eq!(out.len(), CAPACITY);
53
53
                out
54
53
            }
55
53
        }
56
53
    }
_RNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB2_9PublicKey20to_protobuf_encoding
Line
Count
Source
41
167
    pub fn to_protobuf_encoding(&self) -> Vec<u8> {
42
167
        match self {
43
167
            PublicKey::Ed25519(key) => {
44
167
                const CAPACITY: usize = 32 + 4;
45
167
                let mut out = Vec::with_capacity(CAPACITY);
46
501
                for 
slice334
in protobuf::enum_tag_encode(1, 1) {
47
334
                    out.extend_from_slice(slice.as_ref());
48
334
                }
49
501
                for slice in protobuf::bytes_tag_encode(2, 
key167
) {
50
501
                    out.extend_from_slice(slice.as_ref());
51
501
                }
52
167
                debug_assert_eq!(out.len(), CAPACITY);
53
167
                out
54
167
            }
55
167
        }
56
167
    }
57
58
    /// Decode a public key from a Protobuf structure, e.g. read from storage or received from
59
    /// another node.
60
27
    pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, FromProtobufEncodingError> {
61
27
        struct ErrorWrapper(FromProtobufEncodingError);
62
27
        impl<'a> nom::error::ParseError<&'a [u8]> for ErrorWrapper {
63
27
            fn from_error_kind(_: &'a [u8], _: nom::error::ErrorKind) -> Self {
64
0
                ErrorWrapper(FromProtobufEncodingError::ProtobufDecodeError)
65
0
            }
Unexecuted instantiation: _RNvXNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_9PublicKey22from_protobuf_encodingNtB2_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error10ParseErrorRShE15from_error_kind
Unexecuted instantiation: _RNvXNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_9PublicKey22from_protobuf_encodingNtB2_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error10ParseErrorRShE15from_error_kind
66
27
            fn append(_: &'a [u8], _: nom::error::ErrorKind, other: Self) -> Self {
67
0
                other
68
0
            }
Unexecuted instantiation: _RNvXNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_9PublicKey22from_protobuf_encodingNtB2_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error10ParseErrorRShE6append
Unexecuted instantiation: _RNvXNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_9PublicKey22from_protobuf_encodingNtB2_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error10ParseErrorRShE6append
69
27
        }
70
27
        impl<'a> nom::error::FromExternalError<&'a [u8], FromProtobufEncodingError> for ErrorWrapper {
71
27
            fn from_external_error(
72
0
                _: &'a [u8],
73
0
                _: nom::error::ErrorKind,
74
0
                e: FromProtobufEncodingError,
75
0
            ) -> Self {
76
0
                ErrorWrapper(e)
77
0
            }
Unexecuted instantiation: _RNvXs_NvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB7_9PublicKey22from_protobuf_encodingNtB4_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error17FromExternalErrorRShNtB7_25FromProtobufEncodingErrorE19from_external_error
Unexecuted instantiation: _RNvXs_NvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB7_9PublicKey22from_protobuf_encodingNtB4_12ErrorWrapperINtNtCs6ga8gEqbpRc_3nom5error17FromExternalErrorRShNtB7_25FromProtobufEncodingErrorE19from_external_error
78
27
        }
79
27
80
27
        // As indicated in the libp2p specification, the public key must be encoded
81
27
        // deterministically, and thus the fields are decoded deterministically in a precise order.
82
27
        let mut parser = nom::combinator::all_consuming::<_, _, ErrorWrapper, _>(
83
27
            nom::combinator::complete(nom::sequence::tuple((
84
27
                nom::sequence::preceded(
85
27
                    nom::combinator::peek(nom::combinator::verify(
86
27
                        protobuf::tag_decode,
87
27
                        |(field_num, _)| *field_num == 1,
_RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encoding0B8_
Line
Count
Source
87
27
                        |(field_num, _)| *field_num == 1,
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encoding0B8_
88
27
                    )),
89
27
                    nom::combinator::map_res(protobuf::enum_tag_decode, |val| match val {
90
27
                        0..=3 => Ok(val),
91
0
                        _ => Err(FromProtobufEncodingError::UnknownAlgorithm),
92
27
                    }),
_RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings_0B8_
Line
Count
Source
89
27
                    nom::combinator::map_res(protobuf::enum_tag_decode, |val| match val {
90
27
                        0..=3 => Ok(val),
91
0
                        _ => Err(FromProtobufEncodingError::UnknownAlgorithm),
92
27
                    }),
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings_0B8_
93
27
                ),
94
27
                nom::sequence::preceded(
95
27
                    nom::combinator::peek(nom::combinator::verify(
96
27
                        protobuf::tag_decode,
97
27
                        |(field_num, _)| *field_num == 2,
_RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings0_0B8_
Line
Count
Source
97
27
                        |(field_num, _)| *field_num == 2,
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings0_0B8_
98
27
                    )),
99
27
                    nom::combinator::map_res(protobuf::bytes_tag_decode, |d| {
100
27
                        <[u8; 32]>::try_from(d)
101
27
                            .map_err(|_| 
FromProtobufEncodingError::BadEd25519Key0
)
Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB6_9PublicKey22from_protobuf_encodings1_00Ba_
Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_9PublicKey22from_protobuf_encodings1_00Ba_
102
27
                    }),
_RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings1_0B8_
Line
Count
Source
99
27
                    nom::combinator::map_res(protobuf::bytes_tag_decode, |d| {
100
27
                        <[u8; 32]>::try_from(d)
101
27
                            .map_err(|_| FromProtobufEncodingError::BadEd25519Key)
102
27
                    }),
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey22from_protobuf_encodings1_0B8_
103
27
                ),
104
27
            ))),
105
27
        );
106
27
107
27
        match nom::Finish::finish(parser(bytes)) {
108
27
            Ok((_, (1, key))) => Ok(PublicKey::Ed25519(key)),
109
0
            Ok((_, (_, _))) => Err(FromProtobufEncodingError::UnsupportedAlgorithm),
110
0
            Err(err) => Err(err.0),
111
        }
112
27
    }
_RNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB2_9PublicKey22from_protobuf_encoding
Line
Count
Source
60
27
    pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, FromProtobufEncodingError> {
61
27
        struct ErrorWrapper(FromProtobufEncodingError);
62
27
        impl<'a> nom::error::ParseError<&'a [u8]> for ErrorWrapper {
63
27
            fn from_error_kind(_: &'a [u8], _: nom::error::ErrorKind) -> Self {
64
27
                ErrorWrapper(FromProtobufEncodingError::ProtobufDecodeError)
65
27
            }
66
27
            fn append(_: &'a [u8], _: nom::error::ErrorKind, other: Self) -> Self {
67
27
                other
68
27
            }
69
27
        }
70
27
        impl<'a> nom::error::FromExternalError<&'a [u8], FromProtobufEncodingError> for ErrorWrapper {
71
27
            fn from_external_error(
72
27
                _: &'a [u8],
73
27
                _: nom::error::ErrorKind,
74
27
                e: FromProtobufEncodingError,
75
27
            ) -> Self {
76
27
                ErrorWrapper(e)
77
27
            }
78
27
        }
79
27
80
27
        // As indicated in the libp2p specification, the public key must be encoded
81
27
        // deterministically, and thus the fields are decoded deterministically in a precise order.
82
27
        let mut parser = nom::combinator::all_consuming::<_, _, ErrorWrapper, _>(
83
27
            nom::combinator::complete(nom::sequence::tuple((
84
27
                nom::sequence::preceded(
85
27
                    nom::combinator::peek(nom::combinator::verify(
86
27
                        protobuf::tag_decode,
87
27
                        |(field_num, _)| *field_num == 1,
88
27
                    )),
89
27
                    nom::combinator::map_res(protobuf::enum_tag_decode, |val| match val {
90
                        0..=3 => Ok(val),
91
                        _ => Err(FromProtobufEncodingError::UnknownAlgorithm),
92
27
                    }),
93
27
                ),
94
27
                nom::sequence::preceded(
95
27
                    nom::combinator::peek(nom::combinator::verify(
96
27
                        protobuf::tag_decode,
97
27
                        |(field_num, _)| *field_num == 2,
98
27
                    )),
99
27
                    nom::combinator::map_res(protobuf::bytes_tag_decode, |d| {
100
                        <[u8; 32]>::try_from(d)
101
                            .map_err(|_| FromProtobufEncodingError::BadEd25519Key)
102
27
                    }),
103
27
                ),
104
27
            ))),
105
27
        );
106
27
107
27
        match nom::Finish::finish(parser(bytes)) {
108
27
            Ok((_, (1, key))) => Ok(PublicKey::Ed25519(key)),
109
0
            Ok((_, (_, _))) => Err(FromProtobufEncodingError::UnsupportedAlgorithm),
110
0
            Err(err) => Err(err.0),
111
        }
112
27
    }
Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB2_9PublicKey22from_protobuf_encoding
113
114
    /// Convert the [`PublicKey`] into the corresponding [`PeerId`].
115
66
    pub fn into_peer_id(self) -> PeerId {
116
66
        self.into()
117
66
    }
_RNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB2_9PublicKey12into_peer_id
Line
Count
Source
115
24
    pub fn into_peer_id(self) -> PeerId {
116
24
        self.into()
117
24
    }
_RNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB2_9PublicKey12into_peer_id
Line
Count
Source
115
42
    pub fn into_peer_id(self) -> PeerId {
116
42
        self.into()
117
42
    }
118
119
    /// Verifies whether the given signature is valid for the given message using `self` as the
120
    /// public key.
121
24
    pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), SignatureVerifyFailed> {
122
24
        let PublicKey::Ed25519(public_key) = self;
123
24
        let public_key = ed25519_zebra::VerificationKey::try_from(*public_key)
124
24
            .map_err(|_| 
SignatureVerifyFailed()0
)
?0
;
Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey6verify0B8_
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey6verify0B8_
125
24
        let signature =
126
24
            ed25519_zebra::Signature::try_from(signature).map_err(|_| 
SignatureVerifyFailed()0
)
?0
;
Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey6verifys_0B8_
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey6verifys_0B8_
127
24
        public_key
128
24
            .verify(&signature, message)
129
24
            .map_err(|_| 
SignatureVerifyFailed()0
)
?0
;
Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_9PublicKey6verifys0_0B8_
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_9PublicKey6verifys0_0B8_
130
24
        Ok(())
131
24
    }
_RNvMNtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB2_9PublicKey6verify
Line
Count
Source
121
24
    pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), SignatureVerifyFailed> {
122
24
        let PublicKey::Ed25519(public_key) = self;
123
24
        let public_key = ed25519_zebra::VerificationKey::try_from(*public_key)
124
24
            .map_err(|_| SignatureVerifyFailed())
?0
;
125
24
        let signature =
126
24
            ed25519_zebra::Signature::try_from(signature).map_err(|_| SignatureVerifyFailed())
?0
;
127
24
        public_key
128
24
            .verify(&signature, message)
129
24
            .map_err(|_| SignatureVerifyFailed())
?0
;
130
24
        Ok(())
131
24
    }
Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB2_9PublicKey6verify
132
}
133
134
/// Error potentially returned by [`PublicKey::from_protobuf_encoding`].
135
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsh_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_25FromProtobufEncodingErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsh_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_25FromProtobufEncodingErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
136
pub enum FromProtobufEncodingError {
137
    /// Error decoding the Protobuf message.
138
    ProtobufDecodeError,
139
    /// Public key algorithm unknown.
140
    UnknownAlgorithm,
141
    /// Ed25519 key doesn't have a correct length.
142
    BadEd25519Key,
143
    /// Algorithms other than Ed25519 aren't supported.
144
    UnsupportedAlgorithm,
145
}
146
147
/// Call to [`PublicKey::verify`] has failed. No reason is provided for security reasons.
148
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsj_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_21SignatureVerifyFailedNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsj_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_21SignatureVerifyFailedNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
149
pub struct SignatureVerifyFailed();
150
151
/// Public keys with byte-lengths smaller than `MAX_INLINE_KEY_LENGTH` will be
152
/// automatically used as the peer id using an identity multihash.
153
const MAX_INLINE_KEY_LENGTH: usize = 42;
154
155
/// Identifier of a node of the network.
156
///
157
/// The data is a multihash of the public key of the peer.
158
#[derive(Clone, Eq)]
159
pub struct PeerId {
160
    /// Always contains a valid multihash.
161
    multihash: Vec<u8>,
162
}
163
164
impl PeerId {
165
    /// Builds the [`PeerId`] corresponding to a public key.
166
174
    pub fn from_public_key(key: &PublicKey) -> PeerId {
167
174
        let key_enc = key.to_protobuf_encoding();
168
169
174
        let out = if key_enc.len() <= MAX_INLINE_KEY_LENGTH {
170
174
            multihash::Multihash::identity(&key_enc).into_bytes()
171
        } else {
172
0
            let mut out = vec![0; 34];
173
0
            out[0] = 0x12;
174
0
            out[1] = 0x32;
175
0
176
0
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
177
0
            sha2::Digest::update(&mut hasher, &key_enc);
178
0
            sha2::Digest::finalize_into(
179
0
                hasher,
180
0
                sha2::digest::generic_array::GenericArray::from_mut_slice(&mut out[2..]),
181
0
            );
182
0
183
0
            out
184
        };
185
186
174
        PeerId { multihash: out }
187
174
    }
_RNvMs_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_6PeerId15from_public_key
Line
Count
Source
166
28
    pub fn from_public_key(key: &PublicKey) -> PeerId {
167
28
        let key_enc = key.to_protobuf_encoding();
168
169
28
        let out = if key_enc.len() <= MAX_INLINE_KEY_LENGTH {
170
28
            multihash::Multihash::identity(&key_enc).into_bytes()
171
        } else {
172
0
            let mut out = vec![0; 34];
173
0
            out[0] = 0x12;
174
0
            out[1] = 0x32;
175
0
176
0
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
177
0
            sha2::Digest::update(&mut hasher, &key_enc);
178
0
            sha2::Digest::finalize_into(
179
0
                hasher,
180
0
                sha2::digest::generic_array::GenericArray::from_mut_slice(&mut out[2..]),
181
0
            );
182
0
183
0
            out
184
        };
185
186
28
        PeerId { multihash: out }
187
28
    }
_RNvMs_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_6PeerId15from_public_key
Line
Count
Source
166
146
    pub fn from_public_key(key: &PublicKey) -> PeerId {
167
146
        let key_enc = key.to_protobuf_encoding();
168
169
146
        let out = if key_enc.len() <= MAX_INLINE_KEY_LENGTH {
170
146
            multihash::Multihash::identity(&key_enc).into_bytes()
171
        } else {
172
0
            let mut out = vec![0; 34];
173
0
            out[0] = 0x12;
174
0
            out[1] = 0x32;
175
0
176
0
            let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
177
0
            sha2::Digest::update(&mut hasher, &key_enc);
178
0
            sha2::Digest::finalize_into(
179
0
                hasher,
180
0
                sha2::digest::generic_array::GenericArray::from_mut_slice(&mut out[2..]),
181
0
            );
182
0
183
0
            out
184
        };
185
186
146
        PeerId { multihash: out }
187
146
    }
188
189
    /// Checks whether `data` is a valid [`PeerId`].
190
    ///
191
    /// In case of error, returns the bytes passed as parameter in addition to the error.
192
2
    pub fn from_bytes(data: Vec<u8>) -> Result<PeerId, (FromBytesError, Vec<u8>)> {
193
2
        let result = match multihash::Multihash::from_bytes(&data) {
194
2
            Ok(hash) => {
195
2
                // For a PeerId to be valid, it must use either the "identity" multihash code (0x0)
196
2
                // or the "sha256" multihash code (0x12).
197
2
                if hash.hash_algorithm_code() == 0 {
198
2
                    if let Err(
err0
) = PublicKey::from_protobuf_encoding(hash.data()) {
199
0
                        Err(FromBytesError::InvalidPublicKey(err))
200
                    } else {
201
2
                        Ok(())
202
                    }
203
0
                } else if hash.hash_algorithm_code() == 0x12 {
204
0
                    Ok(())
205
                } else {
206
0
                    Err(FromBytesError::InvalidMultihashAlgorithm)
207
                }
208
            }
209
0
            Err((err, _)) => Err(FromBytesError::DecodeError(err)),
210
        };
211
212
2
        match result {
213
2
            Ok(()) => Ok(PeerId { multihash: data }),
214
0
            Err(err) => Err((err, data)),
215
        }
216
2
    }
_RNvMs_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_6PeerId10from_bytes
Line
Count
Source
192
2
    pub fn from_bytes(data: Vec<u8>) -> Result<PeerId, (FromBytesError, Vec<u8>)> {
193
2
        let result = match multihash::Multihash::from_bytes(&data) {
194
2
            Ok(hash) => {
195
2
                // For a PeerId to be valid, it must use either the "identity" multihash code (0x0)
196
2
                // or the "sha256" multihash code (0x12).
197
2
                if hash.hash_algorithm_code() == 0 {
198
2
                    if let Err(
err0
) = PublicKey::from_protobuf_encoding(hash.data()) {
199
0
                        Err(FromBytesError::InvalidPublicKey(err))
200
                    } else {
201
2
                        Ok(())
202
                    }
203
0
                } else if hash.hash_algorithm_code() == 0x12 {
204
0
                    Ok(())
205
                } else {
206
0
                    Err(FromBytesError::InvalidMultihashAlgorithm)
207
                }
208
            }
209
0
            Err((err, _)) => Err(FromBytesError::DecodeError(err)),
210
        };
211
212
2
        match result {
213
2
            Ok(()) => Ok(PeerId { multihash: data }),
214
0
            Err(err) => Err((err, data)),
215
        }
216
2
    }
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_6PeerId10from_bytes
217
218
    /// Returns a raw bytes representation of this `PeerId`.
219
2
    pub fn into_bytes(self) -> Vec<u8> {
220
2
        self.multihash
221
2
    }
_RNvMs_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_6PeerId10into_bytes
Line
Count
Source
219
2
    pub fn into_bytes(self) -> Vec<u8> {
220
2
        self.multihash
221
2
    }
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_6PeerId10into_bytes
222
223
    /// Returns a raw bytes representation of this `PeerId`.
224
85
    pub fn as_bytes(&self) -> &[u8] {
225
85
        &self.multihash
226
85
    }
_RNvMs_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_6PeerId8as_bytes
Line
Count
Source
224
42
    pub fn as_bytes(&self) -> &[u8] {
225
42
        &self.multihash
226
42
    }
_RNvMs_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_6PeerId8as_bytes
Line
Count
Source
224
43
    pub fn as_bytes(&self) -> &[u8] {
225
43
        &self.multihash
226
43
    }
227
228
    /// Returns a base-58 encoded string of this `PeerId`.
229
43
    pub fn to_base58(&self) -> String {
230
43
        bs58::encode(self.as_bytes()).into_string()
231
43
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB4_6PeerId9to_base58
_RNvMs_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB4_6PeerId9to_base58
Line
Count
Source
229
43
    pub fn to_base58(&self) -> String {
230
43
        bs58::encode(self.as_bytes()).into_string()
231
43
    }
232
}
233
234
impl<'a> From<&'a PublicKey> for PeerId {
235
0
    fn from(public_key: &'a PublicKey) -> PeerId {
236
0
        PeerId::from_public_key(public_key)
237
0
    }
Unexecuted instantiation: _RNvXs0_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_9PublicKeyE4from
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_9PublicKeyE4from
238
}
239
240
impl From<PublicKey> for PeerId {
241
66
    fn from(public_key: PublicKey) -> PeerId {
242
66
        PeerId::from_public_key(&public_key)
243
66
    }
_RNvXs1_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert4FromNtB5_9PublicKeyE4from
Line
Count
Source
241
24
    fn from(public_key: PublicKey) -> PeerId {
242
24
        PeerId::from_public_key(&public_key)
243
24
    }
_RNvXs1_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert4FromNtB5_9PublicKeyE4from
Line
Count
Source
241
42
    fn from(public_key: PublicKey) -> PeerId {
242
42
        PeerId::from_public_key(&public_key)
243
42
    }
244
}
245
246
impl fmt::Debug for PeerId {
247
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248
0
        fmt::Display::fmt(self, f)
249
0
    }
Unexecuted instantiation: _RNvXs2_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs2_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
250
}
251
252
impl fmt::Display for PeerId {
253
42
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254
42
        self.to_base58().fmt(f)
255
42
    }
Unexecuted instantiation: _RNvXs3_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
_RNvXs3_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Line
Count
Source
253
42
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254
42
        self.to_base58().fmt(f)
255
42
    }
256
}
257
258
impl cmp::PartialOrd for PeerId {
259
0
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
260
0
        Some(Ord::cmp(self, other))
261
0
    }
Unexecuted instantiation: _RNvXs4_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp10PartialOrd11partial_cmp
Unexecuted instantiation: _RNvXs4_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp10PartialOrd11partial_cmp
262
}
263
264
impl cmp::Ord for PeerId {
265
0
    fn cmp(&self, other: &Self) -> cmp::Ordering {
266
0
        let lhs: &[u8] = self.as_ref();
267
0
        let rhs: &[u8] = other.as_ref();
268
0
        lhs.cmp(rhs)
269
0
    }
Unexecuted instantiation: _RNvXs5_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp3Ord3cmp
Unexecuted instantiation: _RNvXs5_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp3Ord3cmp
270
}
271
272
impl hash::Hash for PeerId {
273
18
    fn hash<H>(&self, state: &mut H)
274
18
    where
275
18
        H: hash::Hasher,
276
18
    {
277
18
        let digest = self.as_ref() as &[u8];
278
18
        hash::Hash::hash(digest, state);
279
18
    }
_RINvXs6_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13EBa_
Line
Count
Source
273
18
    fn hash<H>(&self, state: &mut H)
274
18
    where
275
18
        H: hash::Hasher,
276
18
    {
277
18
        let digest = self.as_ref() as &[u8];
278
18
        hash::Hash::hash(digest, state);
279
18
    }
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtCskQGPRrt89IO_3fnv9FnvHasherECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13ECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashpEBa_
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtCskQGPRrt89IO_3fnv9FnvHasherECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13ECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13ECsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtCskQGPRrt89IO_3fnv9FnvHasherECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13ECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtCskQGPRrt89IO_3fnv9FnvHasherECsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RINvXs6_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB6_6PeerIdNtNtCsaYZPK01V26L_4core4hash4Hash4hashNtNtCsfckpLqgjZhO_9siphasher3sip11SipHasher13ECsibGXYHQB8Ea_25json_rpc_general_requests
280
}
281
282
impl TryFrom<Vec<u8>> for PeerId {
283
    type Error = FromBytesError;
284
285
0
    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
286
0
        PeerId::from_bytes(value).map_err(|(err, _)| err)
Unexecuted instantiation: _RNCNvXs7_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB7_6PeerIdINtNtCsaYZPK01V26L_4core7convert7TryFromINtNtCsdZExvAaxgia_5alloc3vec3VechEE8try_from0Bb_
Unexecuted instantiation: _RNCNvXs7_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB7_6PeerIdINtNtCsaYZPK01V26L_4core7convert7TryFromINtNtCsdZExvAaxgia_5alloc3vec3VechEE8try_from0Bb_
287
0
    }
Unexecuted instantiation: _RNvXs7_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert7TryFromINtNtCsdZExvAaxgia_5alloc3vec3VechEE8try_from
Unexecuted instantiation: _RNvXs7_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert7TryFromINtNtCsdZExvAaxgia_5alloc3vec3VechEE8try_from
288
}
289
290
impl PartialEq<PeerId> for PeerId {
291
12
    fn eq(&self, other: &PeerId) -> bool {
292
12
        let self_digest = self.as_ref() as &[u8];
293
12
        let other_digest = other.as_ref() as &[u8];
294
12
        self_digest == other_digest
295
12
    }
_RNvXs8_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp9PartialEq2eq
Line
Count
Source
291
12
    fn eq(&self, other: &PeerId) -> bool {
292
12
        let self_digest = self.as_ref() as &[u8];
293
12
        let other_digest = other.as_ref() as &[u8];
294
12
        self_digest == other_digest
295
12
    }
Unexecuted instantiation: _RNvXs8_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtCsaYZPK01V26L_4core3cmp9PartialEq2eq
296
}
297
298
impl AsRef<[u8]> for PeerId {
299
42
    fn as_ref(&self) -> &[u8] {
300
42
        self.as_bytes()
301
42
    }
_RNvXs9_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_ref
Line
Count
Source
299
42
    fn as_ref(&self) -> &[u8] {
300
42
        self.as_bytes()
301
42
    }
Unexecuted instantiation: _RNvXs9_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_ref
302
}
303
304
impl FromStr for PeerId {
305
    type Err = ParseError;
306
307
0
    fn from_str(s: &str) -> Result<Self, Self::Err> {
308
0
        let bytes = bs58::decode(s)
309
0
            .into_vec()
310
0
            .map_err(Bs58DecodeError)
311
0
            .map_err(ParseError::Bs58)?;
312
0
        PeerId::from_bytes(bytes).map_err(|(err, _)| ParseError::NotPeerId(err))
Unexecuted instantiation: _RNCNvXsa_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB7_6PeerIdNtNtNtCsaYZPK01V26L_4core3str6traits7FromStr8from_str0Bb_
Unexecuted instantiation: _RNCNvXsa_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB7_6PeerIdNtNtNtCsaYZPK01V26L_4core3str6traits7FromStr8from_str0Bb_
313
0
    }
Unexecuted instantiation: _RNvXsa_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtNtCsaYZPK01V26L_4core3str6traits7FromStr8from_str
Unexecuted instantiation: _RNvXsa_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_6PeerIdNtNtNtCsaYZPK01V26L_4core3str6traits7FromStr8from_str
314
}
315
316
/// Error when turning bytes into a [`PeerId`].
317
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsn_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_14FromBytesErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsn_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_14FromBytesErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
318
pub enum FromBytesError {
319
    /// Failed to decode bytes into a multihash.
320
    DecodeError(multihash::FromBytesError),
321
    /// The algorithm used in the multihash isn't identity or SHA-256.
322
    InvalidMultihashAlgorithm,
323
    /// Multihash uses the identity algorithm, but the data isn't a valid public key.
324
    #[display(fmt = "Failed to decode public key protobuf: {_0}")]
325
    InvalidPublicKey(FromProtobufEncodingError),
326
}
327
328
/// Error when parsing a string to a [`PeerId`].
329
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsp_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_10ParseErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsp_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_10ParseErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
330
pub enum ParseError {
331
    /// Error decoding the Base58 encoding.
332
    #[display(fmt = "Base58 decoding error: {_0}")]
333
    Bs58(Bs58DecodeError),
334
    /// Decoded bytes aren't a valid [`PeerId`].
335
    #[display(fmt = "{_0}")]
336
    NotPeerId(FromBytesError),
337
}
338
339
/// Error when decoding Base58 encoding.
340
0
#[derive(Debug, derive_more::Display, derive_more::From)]
Unexecuted instantiation: _RNvXsr_NtNtCsN16ciHI6Qf_7smoldot6libp2p7peer_idNtB5_15Bs58DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsr_NtNtCseuYC0Zibziv_7smoldot6libp2p7peer_idNtB5_15Bs58DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
341
pub struct Bs58DecodeError(bs58::decode::Error);
342
343
#[cfg(test)]
344
mod tests {
345
    #[test]
346
1
    fn encode_decode_pubkey() {
347
1
        let pub_key = super::PublicKey::Ed25519(rand::random());
348
1
        let protobuf = pub_key.to_protobuf_encoding();
349
1
        assert_eq!(
350
1
            super::PublicKey::from_protobuf_encoding(&protobuf).unwrap(),
351
1
            pub_key
352
1
        );
353
1
    }
354
}