Skip to content

Commit 5a3adad

Browse files
authored
Merge pull request #631 from Winter-Soren/feat/619-store-pubkey-peerid-peerstore
feat: store pubkey and peerid in peerstore
2 parents 4e2be87 + fd818d9 commit 5a3adad

File tree

7 files changed

+365
-7
lines changed

7 files changed

+365
-7
lines changed

examples/doc-examples/example_encryption_insecure.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ async def main():
2424
insecure_transport = InsecureTransport(
2525
# local_key_pair: The key pair used for libp2p identity
2626
local_key_pair=key_pair,
27+
# secure_bytes_provider: Optional function to generate secure random bytes
28+
# (defaults to secrets.token_bytes)
29+
secure_bytes_provider=None, # Use default implementation
30+
# peerstore: Optional peerstore to store peer IDs and public keys
31+
# (defaults to None)
32+
peerstore=None,
2733
)
2834

2935
# Create a security options dictionary mapping protocol ID to transport

libp2p/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ def new_swarm(
200200
key_pair, noise_privkey=noise_key_pair.private_key
201201
),
202202
TProtocol(secio.ID): secio.Transport(key_pair),
203-
TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(key_pair),
203+
TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(
204+
key_pair, peerstore=peerstore_opt
205+
),
204206
}
205207

206208
# Use given muxer preference if provided, otherwise use global default

libp2p/security/insecure/transport.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
from collections.abc import Callable
2+
13
from libp2p.abc import (
4+
IPeerStore,
25
IRawConnection,
36
ISecureConn,
47
)
58
from libp2p.crypto.exceptions import (
69
MissingDeserializerError,
710
)
811
from libp2p.crypto.keys import (
12+
KeyPair,
913
PrivateKey,
1014
PublicKey,
1115
)
@@ -30,11 +34,15 @@
3034
from libp2p.peer.id import (
3135
ID,
3236
)
37+
from libp2p.peer.peerstore import (
38+
PeerStoreError,
39+
)
3340
from libp2p.security.base_session import (
3441
BaseSession,
3542
)
3643
from libp2p.security.base_transport import (
3744
BaseSecureTransport,
45+
default_secure_bytes_provider,
3846
)
3947
from libp2p.security.exceptions import (
4048
HandshakeFailure,
@@ -102,6 +110,7 @@ async def run_handshake(
102110
conn: IRawConnection,
103111
is_initiator: bool,
104112
remote_peer_id: ID | None,
113+
peerstore: IPeerStore | None = None,
105114
) -> ISecureConn:
106115
"""Raise `HandshakeFailure` when handshake failed."""
107116
msg = make_exchange_message(local_private_key.get_public_key())
@@ -164,7 +173,14 @@ async def run_handshake(
164173
conn=conn,
165174
)
166175

167-
# TODO: Store `pubkey` and `peer_id` to `PeerStore`
176+
# Store `pubkey` and `peer_id` to `PeerStore`
177+
if peerstore is not None:
178+
try:
179+
peerstore.add_pubkey(received_peer_id, received_pubkey)
180+
except PeerStoreError:
181+
# If peer ID and pubkey don't match, it would have already been caught above
182+
# This might happen if the peer is already in the store
183+
pass
168184

169185
return secure_conn
170186

@@ -175,6 +191,18 @@ class InsecureTransport(BaseSecureTransport):
175191
transport does not add any additional security.
176192
"""
177193

194+
def __init__(
195+
self,
196+
local_key_pair: KeyPair,
197+
secure_bytes_provider: Callable[[int], bytes] | None = None,
198+
peerstore: IPeerStore | None = None,
199+
) -> None:
200+
# If secure_bytes_provider is None, use the default one
201+
if secure_bytes_provider is None:
202+
secure_bytes_provider = default_secure_bytes_provider
203+
super().__init__(local_key_pair, secure_bytes_provider)
204+
self.peerstore = peerstore
205+
178206
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
179207
"""
180208
Secure the connection, either locally or by communicating with opposing
@@ -183,8 +211,9 @@ async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
183211
184212
:return: secure connection object (that implements secure_conn_interface)
185213
"""
214+
# For inbound connections, we don't know the remote peer ID yet
186215
return await run_handshake(
187-
self.local_peer, self.local_private_key, conn, False, None
216+
self.local_peer, self.local_private_key, conn, False, None, self.peerstore
188217
)
189218

190219
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
@@ -195,7 +224,7 @@ async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureCon
195224
:return: secure connection object (that implements secure_conn_interface)
196225
"""
197226
return await run_handshake(
198-
self.local_peer, self.local_private_key, conn, True, peer_id
227+
self.local_peer, self.local_private_key, conn, True, peer_id, self.peerstore
199228
)
200229

201230

newsfragments/631.feature.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Store public key and peer ID in peerstore during handshake
2+
3+
Modified the InsecureTransport class to accept an optional peerstore parameter and updated the handshake process to store the received public key and peer ID in the peerstore when available.
4+
5+
Added test cases to verify:
6+
1. The peerstore remains unchanged when handshake fails due to peer ID mismatch
7+
2. The handshake correctly adds a public key to a peer ID that already exists in the peerstore but doesn't have a public key yet

0 commit comments

Comments
 (0)