/__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 | | } |