Skip to content

Commit 5377558

Browse files
authored
Merge branch 'master' into kad-in-subst-timeout-upstream
2 parents 36ce9b5 + 3554754 commit 5377558

File tree

9 files changed

+249
-192
lines changed

9 files changed

+249
-192
lines changed

Cargo.lock

Lines changed: 44 additions & 140 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ libp2p-dns = { version = "0.43.0", path = "transports/dns" }
8484
libp2p-floodsub = { version = "0.46.1", path = "protocols/floodsub" }
8585
libp2p-gossipsub = { version = "0.49.0", path = "protocols/gossipsub" }
8686
libp2p-identify = { version = "0.47.0", path = "protocols/identify" }
87-
libp2p-identity = { version = "0.2.10" }
87+
libp2p-identity = { version = "0.2.11" }
8888
libp2p-kad = { version = "0.47.1", path = "protocols/kad" }
8989
libp2p-mdns = { version = "0.47.0", path = "protocols/mdns" }
9090
libp2p-memory-connection-limits = { version = "0.4.0", path = "misc/memory-connection-limits" }

identity/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.2.11
2+
3+
- Switch from `libsecp256` to `k256` for secp256k1 support.
4+
See [PR 5892](https://github.com/libp2p/rust-libp2p/pull/5892)
5+
16
## 0.2.10
27

38
- Deprecate `void` crate.

identity/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "libp2p-identity"
3-
version = "0.2.10"
3+
version = "0.2.11"
44
edition = "2021" # MUST NOT inherit from workspace because we don't want to publish breaking changes to `libp2p-identity`.
55
description = "Data structures and algorithms for identifying peers in libp2p."
66
rust-version = "1.73.0" # MUST NOT inherit from workspace because we don't want to publish breaking changes to `libp2p-identity`.
@@ -16,7 +16,7 @@ asn1_der = { version = "0.7.6", optional = true }
1616
bs58 = { version = "0.5.1", optional = true }
1717
ed25519-dalek = { version = "2.1", optional = true }
1818
hkdf = { version = "0.12.4", optional = true }
19-
libsecp256k1 = { version = "0.7.0", optional = true }
19+
k256 = { version = "0.13.4", optional = true, features = ["ecdsa", "arithmetic"] }
2020
tracing = { workspace = true }
2121
multihash = { version = "0.19.1", optional = true }
2222
p256 = { version = "0.13", default-features = false, features = ["ecdsa", "std", "pem"], optional = true }
@@ -32,7 +32,7 @@ zeroize = { version = "1.8", optional = true }
3232
ring = { workspace = true, features = ["alloc", "std"], optional = true }
3333

3434
[features]
35-
secp256k1 = ["dep:libsecp256k1", "dep:asn1_der", "dep:sha2", "dep:hkdf", "dep:zeroize"]
35+
secp256k1 = ["dep:k256", "dep:asn1_der", "dep:sha2", "dep:hkdf", "dep:zeroize"]
3636
ecdsa = ["dep:p256", "dep:zeroize", "dep:sec1", "dep:sha2", "dep:hkdf"]
3737
rsa = ["dep:ring", "dep:asn1_der", "dep:rand", "dep:zeroize"]
3838
ed25519 = ["dep:ed25519-dalek", "dep:zeroize", "dep:sha2", "dep:hkdf"]

identity/src/secp256k1.rs

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
use core::{cmp, fmt, hash};
2424

2525
use asn1_der::typed::{DerDecodable, Sequence};
26-
use libsecp256k1::{Message, Signature};
27-
use sha2::{Digest as ShaDigestTrait, Sha256};
26+
use k256::{
27+
ecdsa::Signature,
28+
sha2::{Digest as ShaDigestTrait, Sha256},
29+
ProjectivePoint,
30+
};
2831
use zeroize::Zeroize;
2932

3033
use super::error::DecodingError;
@@ -65,7 +68,7 @@ impl fmt::Debug for Keypair {
6568
/// Promote a Secp256k1 secret key into a keypair.
6669
impl From<SecretKey> for Keypair {
6770
fn from(secret: SecretKey) -> Keypair {
68-
let public = PublicKey(libsecp256k1::PublicKey::from_secret_key(&secret.0));
71+
let public = PublicKey(*secret.0.verifying_key());
6972
Keypair { secret, public }
7073
}
7174
}
@@ -79,7 +82,7 @@ impl From<Keypair> for SecretKey {
7982

8083
/// A Secp256k1 secret key.
8184
#[derive(Clone)]
82-
pub struct SecretKey(libsecp256k1::SecretKey);
85+
pub struct SecretKey(k256::ecdsa::SigningKey);
8386

8487
impl fmt::Debug for SecretKey {
8588
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -91,7 +94,7 @@ impl SecretKey {
9194
/// Generate a new random Secp256k1 secret key.
9295
#[cfg(feature = "rand")]
9396
pub fn generate() -> SecretKey {
94-
SecretKey(libsecp256k1::SecretKey::random(&mut rand::thread_rng()))
97+
SecretKey(k256::ecdsa::SigningKey::random(&mut rand::thread_rng()))
9598
}
9699

97100
/// Create a secret key from a byte slice, zeroing the slice on success.
@@ -101,7 +104,7 @@ impl SecretKey {
101104
/// Note that the expected binary format is the same as `libsecp256k1`'s.
102105
pub fn try_from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
103106
let sk_bytes = sk.as_mut();
104-
let secret = libsecp256k1::SecretKey::parse_slice(&*sk_bytes)
107+
let secret = k256::ecdsa::SigningKey::from_slice(sk_bytes)
105108
.map_err(|e| DecodingError::failed_to_parse("parse secp256k1 secret key", e))?;
106109
sk_bytes.zeroize();
107110
Ok(SecretKey(secret))
@@ -131,30 +134,23 @@ impl SecretKey {
131134
///
132135
/// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
133136
pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
134-
let generic_array = Sha256::digest(msg);
137+
use k256::ecdsa::signature::Signer;
135138

136-
// FIXME: Once `generic-array` hits 1.0, we should be able to just use `Into` here.
137-
let mut array = [0u8; 32];
138-
array.copy_from_slice(generic_array.as_slice());
139-
140-
let message = Message::parse(&array);
141-
142-
libsecp256k1::sign(&message, &self.0)
143-
.0
144-
.serialize_der()
145-
.as_ref()
146-
.into()
139+
Signer::<k256::ecdsa::Signature>::sign(&self.0, msg)
140+
.to_der()
141+
.to_bytes()
142+
.into_vec()
147143
}
148144

149145
/// Returns the raw bytes of the secret key.
150146
pub fn to_bytes(&self) -> [u8; 32] {
151-
self.0.serialize()
147+
self.0.to_bytes().into()
152148
}
153149
}
154150

155151
/// A Secp256k1 public key.
156152
#[derive(Eq, Clone)]
157-
pub struct PublicKey(libsecp256k1::PublicKey);
153+
pub struct PublicKey(k256::ecdsa::VerifyingKey);
158154

159155
impl fmt::Debug for PublicKey {
160156
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -193,31 +189,46 @@ impl cmp::Ord for PublicKey {
193189
impl PublicKey {
194190
/// Verify the Secp256k1 signature on a message using the public key.
195191
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
196-
self.verify_hash(Sha256::digest(msg).as_ref(), sig)
192+
let digest = Sha256::new_with_prefix(msg);
193+
self.verify_hash(digest.finalize().as_slice(), sig)
197194
}
198195

199-
/// Verify the Secp256k1 DER-encoded signature on a raw 256-bit message using the public key.
196+
/// Verify the Secp256k1 DER-encoded signature on a raw 256-bit message using the public key.
197+
/// Will return false if the hash is not 32 bytes long, or the signature cannot be parsed.
200198
pub fn verify_hash(&self, msg: &[u8], sig: &[u8]) -> bool {
201-
Message::parse_slice(msg)
202-
.and_then(|m| Signature::parse_der(sig).map(|s| libsecp256k1::verify(&m, &s, &self.0)))
203-
.unwrap_or(false)
199+
Signature::from_der(sig).is_ok_and(|s| {
200+
k256::ecdsa::hazmat::verify_prehashed(
201+
&ProjectivePoint::from(self.0.as_affine()),
202+
msg.into(),
203+
&s,
204+
)
205+
.is_ok()
206+
})
204207
}
205208

206209
/// Convert the public key to a byte buffer in compressed form, i.e. with one coordinate
207210
/// represented by a single bit.
208211
pub fn to_bytes(&self) -> [u8; 33] {
209-
self.0.serialize_compressed()
212+
let encoded_point = self.0.to_encoded_point(true);
213+
debug_assert!(encoded_point.as_bytes().len() == 33);
214+
let mut array: [u8; 33] = [0u8; 33];
215+
array.copy_from_slice(encoded_point.as_bytes());
216+
array
210217
}
211218

212219
/// Convert the public key to a byte buffer in uncompressed form.
213220
pub fn to_bytes_uncompressed(&self) -> [u8; 65] {
214-
self.0.serialize()
221+
let encoded_point = self.0.to_encoded_point(false);
222+
debug_assert!(encoded_point.as_bytes().len() == 65);
223+
let mut array: [u8; 65] = [0u8; 65];
224+
array.copy_from_slice(encoded_point.as_bytes());
225+
array
215226
}
216227

217228
/// Decode a public key from a byte slice in the format produced
218229
/// by `encode`.
219230
pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
220-
libsecp256k1::PublicKey::parse_slice(k, Some(libsecp256k1::PublicKeyFormat::Compressed))
231+
k256::ecdsa::VerifyingKey::from_sec1_bytes(k)
221232
.map_err(|e| DecodingError::failed_to_parse("secp256k1 public key", e))
222233
.map(PublicKey)
223234
}
@@ -232,9 +243,9 @@ mod tests {
232243
fn secp256k1_secret_from_bytes() {
233244
let sk1 = SecretKey::generate();
234245
let mut sk_bytes = [0; 32];
235-
sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
246+
sk_bytes.copy_from_slice(&sk1.to_bytes()[..]);
236247
let sk2 = SecretKey::try_from_bytes(&mut sk_bytes).unwrap();
237-
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
248+
assert_eq!(sk1.to_bytes(), sk2.to_bytes());
238249
assert_eq!(sk_bytes, [0; 32]);
239250
}
240251
}

misc/peer-store/src/memory_store.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::{
1515
};
1616

1717
use libp2p_core::{Multiaddr, PeerId};
18-
use libp2p_swarm::{DialError, FromSwarm};
18+
use libp2p_swarm::{behaviour::ConnectionEstablished, DialError, FromSwarm};
1919
use lru::LruCache;
2020

2121
use super::Store;
@@ -191,21 +191,23 @@ impl<T> Store for MemoryStore<T> {
191191
self.push_event_and_wake(crate::store::Event::RecordUpdated(info.peer_id));
192192
}
193193
}
194-
FromSwarm::ConnectionEstablished(info) => {
194+
FromSwarm::ConnectionEstablished(ConnectionEstablished {
195+
peer_id,
196+
failed_addresses,
197+
endpoint,
198+
..
199+
}) if endpoint.is_dialer() => {
195200
let mut is_record_updated = false;
196201
if self.config.remove_addr_on_dial_error {
197-
for failed_addr in info.failed_addresses {
202+
for failed_addr in *failed_addresses {
198203
is_record_updated |=
199-
self.remove_address_silent(&info.peer_id, failed_addr, false);
204+
self.remove_address_silent(peer_id, failed_addr, false);
200205
}
201206
}
202-
is_record_updated |= self.update_address_silent(
203-
&info.peer_id,
204-
info.endpoint.get_remote_address(),
205-
false,
206-
);
207+
is_record_updated |=
208+
self.update_address_silent(peer_id, endpoint.get_remote_address(), false);
207209
if is_record_updated {
208-
self.push_event_and_wake(crate::store::Event::RecordUpdated(info.peer_id));
210+
self.push_event_and_wake(crate::store::Event::RecordUpdated(*peer_id));
209211
}
210212
}
211213
FromSwarm::DialFailure(info) => {
@@ -302,9 +304,7 @@ impl Config {
302304
}
303305
/// If set to `true`, the store will remove addresses if the swarm indicates a dial failure.
304306
/// More specifically:
305-
/// - Failed dials indicated in
306-
/// [`ConnectionEstablished`](libp2p_swarm::behaviour::ConnectionEstablished)'s
307-
/// `failed_addresses` will be removed.
307+
/// - Failed dials indicated in [`ConnectionEstablished`]'s `failed_addresses` will be removed.
308308
/// - [`DialError::LocalPeerId`] causes the full peer entry to be removed.
309309
/// - On [`DialError::WrongPeerId`], the address will be removed from the incorrect peer's
310310
/// record and re-added to the correct peer's record.
@@ -499,6 +499,7 @@ mod test {
499499
rt.block_on(async {
500500
let (listen_addr, _) = swarm1.listen().with_memory_addr_external().await;
501501
let swarm1_peer_id = *swarm1.local_peer_id();
502+
let swarm2_peer_id = *swarm2.local_peer_id();
502503
swarm2.dial(listen_addr.clone()).expect("dial to succeed");
503504
let handle = spawn_wait_conn_established(swarm1);
504505
swarm2
@@ -508,12 +509,17 @@ mod test {
508509
})
509510
.await;
510511
let mut swarm1 = handle.await.expect("future to complete");
512+
expect_record_update(&mut swarm2, swarm1_peer_id).await;
511513
assert!(swarm2
512514
.behaviour()
513515
.address_of_peer(&swarm1_peer_id)
514516
.expect("swarm should be connected and record about it should be created")
515517
.any(|addr| *addr == listen_addr));
516-
expect_record_update(&mut swarm1, *swarm2.local_peer_id()).await;
518+
// Address from connection is not stored on the listener side.
519+
assert!(swarm1
520+
.behaviour()
521+
.address_of_peer(&swarm2_peer_id)
522+
.is_none());
517523
let (new_listen_addr, _) = swarm1.listen().with_memory_addr_external().await;
518524
let handle = spawn_wait_conn_established(swarm1);
519525
swarm2
@@ -590,15 +596,18 @@ mod test {
590596
.await
591597
.expect("future to complete");
592598
let mut swarm1 = handle.await.expect("future to complete");
593-
// expexting update from direct connection.
594599
expect_record_update(&mut swarm2, swarm1_peer_id).await;
595600
assert!(swarm2
596601
.behaviour()
597602
.peer_store
598603
.address_of_peer(&swarm1_peer_id)
599604
.expect("swarm should be connected and record about it should be created")
600605
.any(|addr| *addr == listen_addr));
601-
expect_record_update(&mut swarm1, *swarm2.local_peer_id()).await;
606+
assert!(swarm1
607+
.behaviour()
608+
.peer_store
609+
.address_of_peer(&swarm2_peer_id)
610+
.is_none());
602611
swarm1.next_swarm_event().await; // skip `identify::Event::Sent`
603612
swarm1.next_swarm_event().await; // skip `identify::Event::Received`
604613
let (new_listen_addr, _) = swarm1.listen().with_memory_addr_external().await;

protocols/request-response/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- feat: add `Behaviour::send_request_with_addresses()`
77
See [PR 5938](https://github.com/libp2p/rust-libp2p/issues/5938).
88

9+
- fix: don't fail outbound request on `DialError::DialPeerConditionFalse`.
10+
See [PR 6000](https://github.com/libp2p/rust-libp2p/pull/6000)
11+
912
## 0.28.0
1013

1114
- Deprecate `void` crate.

protocols/request-response/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ use libp2p_identity::PeerId;
9090
use libp2p_swarm::{
9191
behaviour::{AddressChange, ConnectionClosed, DialFailure, FromSwarm},
9292
dial_opts::DialOpts,
93-
ConnectionDenied, ConnectionHandler, ConnectionId, NetworkBehaviour, NotifyHandler,
93+
ConnectionDenied, ConnectionHandler, ConnectionId, DialError, NetworkBehaviour, NotifyHandler,
9494
PeerAddresses, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm,
9595
};
9696
use smallvec::SmallVec;
@@ -706,9 +706,13 @@ where
706706
DialFailure {
707707
peer_id,
708708
connection_id,
709-
..
709+
error,
710710
}: DialFailure,
711711
) {
712+
if let DialError::DialPeerConditionFalse(_) = error {
713+
// Dial-condition fails because there is already another ongoing dial.
714+
return;
715+
}
712716
if let Some(peer) = peer_id {
713717
// If there are pending outgoing requests when a dial failure occurs,
714718
// it is implied that we are not connected to the peer, since pending

0 commit comments

Comments
 (0)